Ответ на аналогичный вопрос для Android Compose был дан в этом посте . Мне было интересно, можно ли сделать то же самое для SwiftUI?
Пример:
HStack {
VStack {
ContentWithUnknownHeight()
NextContentWithUnknownHeight()
}
.frame(width: geometry.size.width * 0.8)
Image("User")
.resizable()
.frame(width: geometry.size.width * 0.2)
}
.frame(minHeight: 100)
Высота HStack не должна быть фиксированной, а должна увеличиваться, если это делают его дочерние элементы. Если VStack выше изображения, как я могу заполнить высоту изображения до высоты его родителя, не влияя на его высоту?
Что у меня есть:
Ожидаемый результат:
Я бы предложил отредактировать вопрос, чтобы было ясно, какой тип представления вы хотите расширить, чтобы заполнить стек. Различные взгляды ведут себя по-разному. Если вы имеете в виду Image, сделайте формулировку менее общей.
@Sweeper Привет, спасибо! .fixedSize(horizontal: false, vertical: true) это действительно то, что я искал! Также спасибо за предложение - исправил мой вопрос и детали для ясности. Я понял, что scaledToFit неприменимо к моему случаю, поэтому удалил его, но scaleToFill сделал свое дело. Если вы также можете опубликовать ответ, я приму его.





HStack автоматически принимает рост самого высокого ребенка.
Однако ваш вопрос, похоже, больше касается высоты ребенка внутри HStack, и в вашем примере кода изображение находится в этой позиции. Предполагая, что вы действительно хотите масштабировать изображение для заполнения (в отличие от масштабирования по размеру, как это реализовано в коде), то один из способов — показать изображение в виде наложения поверх HStack:
.frame, который устанавливает фиксированную высоту для HStack.Image внутри HStack на Spacer.HStack будет определять первый ребенок.alignment: .trailing.HStack {
VStack {
SomeMoreContentWithUnknownHeight()
}
.frame(width: geometry.size.width * 0.8)
Spacer()
}
.overlay(alignment: .trailing) {
Image("User")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width * 0.2)
.clipped()
}

Если SomeMoreContentWithUnknownHeight — единственный контент, оставшийся в HStack, то вам даже не нужно использовать HStack, вместо этого вы можете применить наложение непосредственно к этому контенту. Просто используйте отступы, чтобы зарезервировать место для содержимого наложения:
SomeMoreContentWithUnknownHeight()
.frame(maxWidth: .infinity)
.padding(.trailing, geometry.size.width * 0.2)
.overlay(alignment: .trailing) {
Image("User")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width * 0.2)
.clipped()
}
Чтобы HStack не вырастал выше, чем нужно самому высокому ребенку, добавьте
.fixedSize(horizontal: false, vertical: true)
в HStack.
Затем, если другие представления являются представлениями, которые естественным образом расширяются (например, Divider, Rectangle, Image(...).resizable()), они будут расширяться, автоматически заполняя высоту. Для изображения вы можете захотеть, чтобы оно было scaledToFill, как в ответе Бензи Низа.
Для представлений, которые не расширяются естественным образом, например Text, вы можете заставить их делать это, поместив их как наложение на какое-либо представление, которое расширяется естественным образом, плюс maxHeight: .infinity.
Color.clear // Colors naturally expand
.overlay {
Text("Foo")
.frame(maxHeight: .infinity)
.background(.yellow) // this background will fill the whole height
}
Некоторые виды, такие как Button, могут нуждаться в специальной обработке, чтобы расширить область касания, а не только рамку. См. также SwiftUI: увеличение области касания/перетаскивания для взаимодействия с пользователем
Button("Foo") { /* ... */ }
.frame(maxHeight: .infinity)
.background(.yellow)
.contentShape(Rectangle())
Как насчет того, чтобы поставить
.fixedSize(horizontal: false, vertical: true)наHStack? В зависимости от того, что представляет собой желто-зеленый вид, вам потребуется выполнить с ним некоторые дополнительные действия. Для образа достаточно сделатьresizable, и не стоит этого делать.scaledToFit().