Saltar al contenido

Layout: stacks, grids y espaciado

Coloca las cosas en pantalla con VStack, HStack, ZStack, Spacer y Grid. Alignment, frames y el modelo de layout que hace SwiftUI predecible.

Todo diseño de interfaz es, en el fondo, colocar cosas: en fila, en columna, encima. SwiftUI lo resuelve con contenedores simples que se combinan. Domina cuatro o cinco y podrás construir casi cualquier pantalla.

  • Apilar con VStack, HStack y ZStack.
  • Empujar y separar con Spacer y spacing.
  • Alinear con alignment.
  • Rejillas con Grid y control de tamaño con frame.

Los tres stacks

VStack

Apila en vertical (columna). De arriba abajo.

HStack

Apila en horizontal (fila). De izquierda a derecha.

ZStack

Apila en profundidad (capas). Uno encima de otro.

SWIFT
VStack {    Text("Arriba")    Text("Abajo")}HStack {    Image(systemName: "star")    Text("Al lado")}ZStack {    Color.blue                     // fondo    Text("Encima").foregroundStyle(.white)}

Espaciado y Spacer

Cada stack acepta spacing para separar sus hijos. Y Spacer() es un elemento elástico que empuja el resto:

SWIFT
VStack(spacing: 20) {          // 20 puntos entre elementos    Text("Título")    Text("Subtítulo")}HStack {    Text("Izquierda")    Spacer()                   // empuja hacia los extremos    Text("Derecha")}

Spacer es tu mejor amigo para alinear

En vez de calcular márgenes, deja que Spacer() haga el trabajo: uno antes empuja a la derecha/abajo, uno después a la izquierda/arriba, uno a cada lado centra. Es la forma más natural de distribuir espacio en SwiftUI.

Alignment

Cada stack alinea sus hijos en el eje perpendicular. Un VStack alinea en horizontal:

SWIFT
VStack(alignment: .leading) {   // .leading, .center, .trailing    Text("Alineado")    Text("a la izquierda")}HStack(alignment: .top) {        // .top, .center, .bottom    Text("Arriba")    Text("del todo")}

Grid

Para rejillas de filas y columnas alineadas, Grid (iOS 16+):

SWIFT
Grid {    GridRow {        Text("Nombre"); Text("Ana")    }    GridRow {        Text("Edad"); Text("30")    }}

Para colecciones que se desplazan, usarás LazyVGrid / LazyHGrid (cargan solo lo visible), que verás con las listas.

frame: controlar el tamaño

Por defecto, una vista ocupa lo que necesita. frame te deja fijar tamaños o pedir que se expanda:

SWIFT
Text("Botón")    .frame(maxWidth: .infinity)      // ocupa todo el ancho disponible    .frame(height: 50)    .background(.blue)

maxWidth: .infinity es el truco para que un elemento se estire hasta llenar su contenedor — habitual en botones a ancho completo.

El layout de SwiftUI es una negociación

El modelo mental correcto: el padre propone un tamaño al hijo, el hijo elige el suyo dentro de esa propuesta, y el padre lo coloca. Un Text elige lo justo para su contenido; con .frame(maxWidth: .infinity) elige estirarse. Cuando algo no se coloca donde esperas, piensa en esa conversación padre↔hijo: casi siempre el hijo está eligiendo un tamaño distinto al que imaginabas. Entender esta negociación te ahorra la frustración clásica del principiante con el layout.

Compón una pantalla

  1. Haz un VStack con un título y un subtítulo, alineados a .leading.
  2. Crea una fila (HStack) con un texto a la izquierda y otro a la derecha usando Spacer().
  3. Superpón un Text sobre un Color con ZStack.
  4. Haz un botón a ancho completo con .frame(maxWidth: .infinity).
  5. Prueba una rejilla simple con Grid y GridRow.