Pintemos una vista con un Text y un Image, como se muestra a continuación:
var body: some View {
Image(systemName: "table")
.resizable()
.frame(width: size, height: size)
.overlay {
Circle().stroke(Color.gray, lineWidth: 1)
}
.background(Color(white: 0.9))
.foregroundStyle(.red)
.clipShape(Circle())
Text("Welcome to Kuchi")
.font(.system(size: 30))
.bold()
.foregroundColor(.red)
.lineLimit(2)
.multilineTextAlignment(.center)
}
Esta no es la forma correcta de añadir varias subvistas a una vista. Con algunas excepciones, la propiedad body de una vista espera solo una subvista.
En SwiftUI 1.0, el código de arriba habría provocado un error de compilación. Ahora compila e incluso funciona en el simulador: todas las subvistas están apiladas de forma vertical.
Si se quiere empaquetar más de una subvista en una vista, se debe usar un contenedor. El más usado es el (-)Stack, que viene siendo la versión análoga del UIStackView de UIKit.
(-)Stack
En SwiftUI podemos agrupar elementos de una pila de forma horizontal, vertical, o uno sobre otro. Para esto se usan los componentes HStack, VStack y ZStack respectivamente, que reciben un conjunto de componentes visuales en una función @ViewBuilder, y los pinta a todos de una sola vez, independiente de que esté en o fuera de la pantalla.
Se sugiere usar este tipo de pilas de vistas cuando se tenga un número pequeño de subvistas o no se quiera retrasar el pintado con la versión "perezosa" de los contenedores.
Las pilas de vistas (sin importar la dirección) reciben por constructor:
-
alignment: La guía de alineación de subvistas en el stack. Para elVStackserá de tipoHorizontalAlignment, para elHStackseráVerticalAlignmenty para ZStack seráAlignment. -
spacing: La distancia entre subvistas adyacentes onilsi se quiere que el stack ponga la distancia por defecto entre un par de subvistas. -
content: UnViewBuilderque crea el contenido del stack.
VStack
Distribuye los componentes en dirección vertical.
var body: some View {
VStack(
alignment: .leading,
spacing: 10
) {
ForEach(
1...10,
id: \.self
) {
Text("Item \($0)")
}
}
}
La propiedad alignment sirve para alinear las vistas dentro del Stack. Por defecto tiene el valor .center, sin embargo, podríamos alinear los componentes hacia uno de los extremos de la fila con .leading y .trailing.
HStack
Distribuye los componentes en dirección horizontal.
private struct VerticalAlignmentGallery: View {
var body: some View {
VStack(spacing: 30) {
row(alignment: .top, text: "Top")
row(alignment: .center, text: "Center")
row(alignment: .bottom, text: "Bottom")
row(alignment: .firstTextBaseline, text: "First Text Baseline")
row(alignment: .lastTextBaseline, text: "Last Text Baseline")
}
}
private func row(alignment: VerticalAlignment, text: String) -> some View {
HStack(alignment: alignment, spacing: 0) {
Color.red.frame(height: 1)
Text(text).font(.title).border(.gray)
Color.red.frame(height: 1)
}
}
}
Parecido al caso del VStack, la propiedad alignment sirve para alinear las vistas dentro del Stack. Por defecto tiene el valor .center, sin embargo, podríamos alinear los componentes hacia uno de los extremos de la columna con .top y .bottom.
ZStack
Partiendo de que la dirección Z es perpendicular al plano de la pantalla, el ZStack apila elementos uno sobre otro. Items "arriba" del closure aparecerán "más abajo" en el stack view. Sería como poner la primera vista sobre la superficie de la pantalla, luego apilar la siguiente vista encima y así sucesivamente.
Group
Group es otro contenedor que no pinta nada en pantalla. Es útil cuando se necesita envolver código que es más complicado que una sola vista.
Modificadores de contenedores
Cuando se tenga una vista contenedora y se quiera aplicar uno o más modificadores a todas las subvistas, se puede aplicar los modificadores al contenedor.
Por ejemplo, en lugar de escribir:
VStack {
Text("Welcome")
.font(.system(size: 30))
.bold()
.foregroundStyle(.red)
.lineLimit(2)
.multilineTextAlignment(.center)
Text("to Kuchi")
.font(.system(size: 30))
.bold()
.foregroundStyle(.red)
.lineLimit(2)
.multilineTextAlignment(.center)
}
Se puede escribir:
VStack {
Text("Welcome")
.font(.system(size: 30))
.bold()
Text("to Kuchi")
.font(.system(size: 30))
.bold()
}
.foregroundStyle(.red)
.lineLimit(2)
.multilineTextAlignment(.center)
Teniendo en cuenta que .foregroundStyle(.red), .lineLimit(2) y .multilineTextAlignment(.center).
En versiones anterior de SwiftUI font(.system(size: 30)) y .bold() no podían ser aplicados al contenedor porque eran modificadores de Text. Sin embargo, actualmente pueden ser aplicados al contenedor, quien propaga la modificación hacia las instancias de Text contenidas.
El código anterior quedaría de esta forma:
VStack {
Text("Welcome")
Text("to Kuchi")
}
.font(.system(size: 30))
.bold()
.foregroundStyle(.red)
.lineLimit(2)
.multilineTextAlignment(.center)
Aunque aplicar un modificador al contenedor puede propagar efectos en las subvistas, este puede ser sobre-escrito en cada subvista. Por ejemplo, aunque se definió la fuente en 30 en el contenedor, puedo cambiar la fuente en uno de los Text y esto va a tener más prioridad:
VStack {
Text("Welcome")
.font(.headline)
Text("to Kuchi")
}
.font(.system(size: 30))
.bold()
.foregroundStyle(.red)
.lineLimit(2)
.multilineTextAlignment(.center)
Top comments (0)