Позиционирование внутри ZStack
Я хочу, чтобы этот красный прямоугольник был перемещен в левый нижний угол, но по какой-то причине мои выравнивания и отступы не работают так, как я ожидал. Что я делаю неправильно и как переместить его в левый нижний угол?
Код:
struct ContentView: View {
var body: some View {
ZStack {
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
}
}
}
2 ответа
Ответ Йодагамы может быть тем, что вы хотите, но стоит также изучить ваше замешательство, потому что макет SwiftUI не работает так, как вы думаете. Звонки типа
Я разберу, что происходит в вашем коде, начиная с внутренней части и заканчивая разработкой.
Rectangle()
Это создает прямоугольник, который заполняет любое пространство, которое ему дано.
Rectangle()
.fill(Color.blue)
Это встраивает прямоугольник в новый вид, который устанавливает синий цвет «заливки» в среде.
Rectangle()
.fill(Color.blue)
.frame(width: 197, height: 163)
Это встраивает это в новый вид с фиксированным размером (197x163). Встроенное представление располагается по центру, но поскольку прямоугольник занимает все доступное пространство, он заполняет рамку.
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
Это встраивает этот фрейм в VStack, в котором нет промежутков между его элементами (но это не имеет значения, потому что он только один). Размер VStack точно такой же, как у его дочерних элементов (197x163).
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
Это центрирует VStack 197x163 внутри нового представления с фиксированным разрешением 284x269. Он не устанавливает размер VStack равным 284x269. VStacks всегда точно такого же размера, как и их дочерние элементы. Это конкретное место, где вы ошиблись (я объясню, как это исправить, после того, как пройдусь по остальным).
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
Это создает новый вид, в который встроен кадр 284x269 с 0 дополнительными отступами слева (так что этот новый вид имеет точно такой же размер, как текущий кадр, и это ничего не делает). Затем он встраивает это в новый вид, который добавляет 0 дополнительных отступов внизу. Опять же, это вообще ничего не дает.
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
Это встраивает все это в новый вид, который рисует синий фон точно такого же размера, как встроенный вид (284x269).
ZStack {
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
}
}
И, наконец, все это сосредоточено внутри ZStack. ZStack имеет именно тот размер, который необходим для размещения его дочерних элементов, то есть 284x269. Это вообще ничего не делает.
Итак, как это исправить. Вы ошиблись в том, как VStack был расположен в окружающем его фрейме. Он был по центру, но вы хотели, чтобы он был выровнен. Здесь нет необходимости в ZStack или даже в VStack. Вы делаете это так:
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
.frame(width: 284, height: 269, alignment: .bottomLeading) // <===
.background(Color.blue)
Обратите внимание, как последовательно создаются два кадра View. Первый ограничивает прямоугольник. Второй встраивает и выравнивает это в большей рамке. Это хороший пример того, насколько SwiftUI настолько отличается от того, что думают разработчики. На самом деле это можно еще больше упростить, так как Color заполняет все предлагаемое пространство, как и Rectangle:
Color.red
.frame(width: 197, height: 163)
.frame(width: 284, height: 269, alignment: .bottomLeading)
.background(Color.blue)
Но я часто нахожу, что это лучше и гибче с прокладками, когда это возможно. По моему опыту, распорки работают лучше, когда у вас нет фиксированных размеров кадра для всего. (Я не говорю, что это обязательно лучшая практика; это просто мой опыт. SwiftUI довольно новый, и мы все еще выясняем, что такое лучшая практика.)
VStack {
Spacer() // Fill all space above
HStack {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
Spacer() // Fill all space to the right
}
}
.frame(width: 284, height: 269)
.background(Color.blue)
ZStack имеет параметр
alignment: Alignment
что является выравниванием по обеим осям.
struct ContentView: View {
var body: some View {
ZStack(alignment:.bottomLeading) {
Rectangle()
.fill(Color.blue)
.frame(width: 284, height: 269)
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
}
}