Как сделать ширину просмотра равной 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)
}
Но я не уверен, что это лучшее. Может быть, кто-то найдет более элегантное решение /