Центр обзора по горизонтали в SwiftUI

Как я могу центрировать горизонтально View (Image) в HStack? Я хочу, чтобы кнопка была выровнена по левому краю, а изображение было центрировано по горизонтали.

В настоящее время у меня есть эта структура:

VStack {
        HStack {
            Button(action: {
                print("Tapped")
            }, label: {
                Image("left-arrow")
                    .resizable()
                    .frame(width: 30, height: 30, alignment: .leading)
            }).padding(.leading, 20)

            Spacer()

            Image("twitter-logo")
                .resizable()
                .frame(width: 30, height: 30, alignment: .center)

        }
        Spacer()
    }

Что дает мне это:

Но я хочу добиться этого:

Обновить:

9 ответов

Решение

Как насчет сохранения размера кнопки в свойстве и добавления к изображению отрицательного отступа? И обратите внимание на дополнительную проставку после изображения.

struct ContentView: View {

    var buttonSize: Length = 30

    var body: some View {
        VStack {
            HStack {
                Button(action: {
                    print("Tapped")
                }, label: {
                    Image(systemName: "star")
                        .resizable()
                        .frame(width: buttonSize, height: buttonSize, alignment: .leading)
                })
                Spacer()
                Image(systemName: "star")
                    .resizable()
                    .frame(width: 30, height: 30, alignment: .center)
                    .padding(.leading, -buttonSize)
                Spacer()
            }
            Spacer()
        }
    }
}

Результат:

Вы можете вставить два HStackв ZStack и разместите распорки соответственно для горизонтального расстояния. Вставить все это в VStack с Spacer() чтобы все было доведено до вершины.

struct ContentView : View {
var buttonSize: Length = 30
var body: some View {
    VStack {
        ZStack {
            HStack {
                Button(action: {

                }, label: {
                    Image(systemName: "star")
                        .resizable()
                        .frame(width: CGFloat(30), height: CGFloat(30), alignment: .leading)
                }).padding(.leading, CGFloat(20))

                Spacer()
            }

            HStack {
                Image(systemName: "star")
                    .resizable()
                    .frame(width: CGFloat(30), height: CGFloat(30), alignment: .center)
            }
        }
        Spacer()
    }
}

}

Примечание: во втором HStack, изображение должно автоматически выравниваться по центру, но если это не так, вы можете поместить Spacer() до и после изображения.

Редактировать: Добавлено VStack а также Spacer() переместить все наверх, как хотел ОП.

Редактировать 2: Убрал отступы на изображении, потому что это вызвало небольшое смещение изображения от центра. Так как это по-своему HBox и выровненный по центру, он не нуждается в заполнении.

Самый простой способ для меня:

ZStack(){
    HStack{
        Image("star").resizable().foregroundColor(.white).frame(width: 50, height: 50)
        Spacer()
    }
        Image("star").resizable().font(.title).foregroundColor(.white).frame(width: 50, height: 50)
}

Вы центрируете представление, используя свойство позиции, попробуйте этот код

Group{ // container View
   Image("twitter-logo")
            .resizable()
            .frame(width: 30, height: 30, alignment: .center)
}.position(x: UIScreen.main.bounds.width/2)

правильный способ центрировать заголовок как панель навигации:

      HStack {

    Spacer()
        .overlay {
            HStack {
                Image(systemName: "star")
                Spacer()
            }
        }

    Text("Title")
             
    Spacer()
        .overlay {
            HStack {
                Spacer()
                Image(systemName: "star")
            }
        }
}

Вот что сработало для меня

      HStack {
    Image(systemName: "star.fill")
       .frame(maxWidth: .infinity, alignment: .leading)
    Image(systemName: "star.fill")
       .frame(maxWidth: .infinity, alignment: .center)
    Text("")
       .frame(maxWidth: .infinity, alignment: .trailing)
}
.foregroundColor(.yellow)

Вдохновленный SwiftUI — как выровнять элементы слева, по центру и справа в HStack?

Вы можете поместить вид, который вы хотите центрировать, в а затем установитьalignmentкcenter. Убедитесь, что вы также установилиframe(maxWidth: .infinity)иначе он будет центрировать ваш взгляд наVStackможет не занимать всю ширину экрана, поэтому вы можете не получить желаемого внешнего вида.

Чтобы сделать это еще проще, напишите это как функцию, котораяextendsвViewобъект

      extension View {
    func centerInParentView() -> some View {
        VStack(alignment: .center) {
            self
        }
        .frame(maxWidth: .infinity)
    }
}

И тогда вы можете просто вызвать его, как модификатор вида, т.е.

      VStack {
        HStack {
            Button(action: {
                print("Tapped")
            }, label: {
                Image("left-arrow")
                    .resizable()
                    .frame(width: 30, height: 30, alignment: .leading)
            }).padding(.leading, 20)
            
            Spacer()
            
            Image("twitter-logo")
                .resizable()
                .frame(width: 30, height: 30, alignment: .center)
            
        }
        Spacer()
}
.centerInParentView()

Работает каждый раз для меня

У меня есть альтернативное решение. Я использовал скрытое изображение в качестве заполнителя.

      HStack {
    Image("left-arrow").padding()
    Spacer()
    Image("twitter-logo")
    Spacer()
    // placeholder to keep layout symmetric
    Image("left-arrow").padding().hidden()
}

Конечно, вы можете заменить изображения кнопками или другими представлениями по своему усмотрению.

Предлагаю другое решение:

https://gist.github.com/buscarini/122516641cd0ee275dd367786ff2a736

Его можно использовать следующим образом:

      HStack {
    Color.red
        .frame(width: 0, height: 50)
        .layoutPriority(1)
        
    GlobalHCenteringView {
        Text("Hello, world!")
            .lineLimit(1)
            .background(Color.green)
    }
    .background(Color.yellow)
    
    Color.red
        .frame(width: 180, height: 50)
        .layoutPriority(1)
    }
}

Это будет центрировать дочерний вид на экране, если он подходит, или оставить его как есть, если он не подходит. В настоящее время он использует UIScreen, поэтому он работает только на iOS, но вы можете легко передать ширину экрана или родителя конструктору представления, получив его из GeometryReader или чего-то еще.

Другие вопросы по тегам