Как сделать ширину просмотра равной superview с помощью swiftUI

У меня есть Button

struct ContentView : View {
var body: some View {
    HStack {
        Button(action: {}) {
            Text("MyButton")
                .color(.white)
                .font(Font.system(size: 17))
        }
        .frame(height: 56)
        .background(Color.red, cornerRadius: 0)
    }
}
}

Но я хочу прикрепить это к краям supreview (трейлинг к трейлингу и лидерству superview). Нравится:

HStack не помогает мне, и он ожидает Исправлена frame или ширина равна UIScree.size не являются гибкими решениями.

6 ответов

Решение

Вам нужно использовать .frame(minWidth: 0, maxWidth: .infinity) модификатор

Добавьте следующий код

        Button(action: tap) {
            Text("Button")
                .frame(minWidth: 0, maxWidth: .infinity)
                .background(Color.red)
        }
        .padding([.leading, .trailing], 20)

Модификатор отступа позволит вам иметь некоторое пространство от края.

Имейте в виду, что порядок модификаторов важен. Потому что модификаторы на самом деле являются функциями, которые оборачивают представление ниже (они не изменяют свойства представлений)

Вы можете использовать GeometryReader: https://developer.apple.com/documentation/swiftui/geometryreader

По словам Apple:

Это представление возвращает гибкий предпочтительный размер в родительский макет.

Это гибкое решение, так как оно меняется в соответствии с изменениями родительского макета.

Вот чистое решение SwiftUI, в котором вы хотите заполнить ширину родительского элемента, но ограничить высоту произвольным соотношением сторон (скажем, вам нужны квадратные изображения):

            ZStack {
                Image("myImage")
                    .resizable()
                    .scaledToFill()
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
                    .clipped()
            }
            .aspectRatio(1.0, contentMode: .fill)

Просто замените 1.0 на любое желаемое соотношение сторон.

Я потратил около дня, пытаясь понять это, потому что я не хотел использовать GeometryReader или UIScreen.main.bounds (что не является кроссплатформенным)

Простое добавление следующего в ваш код заставит кнопку расширяться от края до края. (Вы также можете добавить отступы, если хотите)

.frame(minWidth: 0, maxWidth: .infinity)

Весь код кнопки будет выглядеть так:

struct ContentView : View {
    var body: some View {
        HStack {
            Button(action: {}) {
                Text("MyButton")
                    .color(.white)
                    .font(Font.system(size: 17))
            }
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding(.top, 8)
            .padding(.bottom, 8)
            .background(Color.red, cornerRadius: 0)
        }
    }
}

iOS 17

Начиная с iOS 17, правильный способ сделать это — использовать.containerRelativeFrameмодификатор, потому что использование.infinityширина фрейма фактически приводит к тому, что родительский фрейм имеет бесконечную ширину.

Итак, это было бы так:

      Button(action: {}) {
    Text("MyButton")
        .foregroundStyle(.white)
        .containerRelativeFrame(.horizontal) //  This should be inside the `label` parameter of the `button`. Otherwise it would be NOT touchable
        .padding(-10) //  This is here to make space to the edges. Yes it should have a NEGATIVE value
}
.frame(height: 56)
.background(.red)

Я нашел одно решение:

var body: some View {
    Button(action: {}) {
            HStack {
                Spacer()
                Text("MyButton")
                    .color(.white)
                    .font(Font.system(size: 17))
                Spacer()
            }
            .frame(height: 56)
            .background(Color.red, cornerRadius: 0)
        }.padding(20)
}

Но я не уверен, что это лучшее. Может быть, кто-то найдет более элегантное решение /

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