Civil & Structural Engineering
How to Create a Dynamic Collection View Layout in Swiftui
Table of Contents
Introducción a las vistas de la colección dinámica en SwiftUI
Aplicaciones iOS modernas exigen fluidos, interfaces adaptables que respondan con gracia a diferentes tamaños de datos, orientaciones de dispositivos y dimensiones de pantalla. En UIKit, las vistas de la colección proporcionan un poderoso pero verboso mecanismo para la construcción de diseños similares a la red. SwiftUI simplifica esto dramáticamente con su API declarativa, particularmente a través de
Una disnómica colección vista diseño adapta su cuenta de columna, altura de fila, espaciamiento o comportamiento de tamaño basado en el ancho de contenedor disponible, el número de elementos, o el contenido mismo. Este artículo le guiará mediante la construcción de tales diseños en SwiftUI, cubriendo todo desde la configuración de la red básica a comportamientos avanzados adaptables, ajuste de rendimiento e integración con animaciones sólidas.
Componentes básicos: LazyVGrid y LazyHGrid
SwiftUI proporciona dos contenedores de rejilla primaria: LazyVGrid (rejilla vertical de desplazamiento) y LazyHGrid (rejilla de desplazamiento horizontal) Ambos cargan lazimente a sus hijos, lo que significa que las vistas se crean sólo cuando se hacen visibles en pantalla – una característica crucial para manejar grandes conjuntos de memoria
Configuración de GridItem
Para definir la estructura de una cuadrícula, usted crea una matriz de GridItem instancias. Cada representa una sola columna (en ) o una sola fila (en ]).Usted controla tres propiedades clave:
- Tamaño] – Uno de los tres modos de tamaño: , , o .
- Pasado] – Espaciado horizontal entre elementos en la misma fila (para rejillas verticales) o espaciamiento vertical (para rejillas horizontales).
- Alignación – Controla cómo los elementos se alinean dentro de una célula de red. Raramente cambió de los defectos.
La elección del modo de tamaño define la flexibilidad de diseño general:
- Fixed – Ancho de explicidad (o altura) para cada columna/huevo. Útil cuando se necesita el tamaño exacto, por ejemplo, un diseño de tres columnas de células fijas de 100 puntos.
- Flexible] – Cada elemento de red puede estirarse para llenar el espacio disponible, con límites mínimos y máximos opcionales. Esta es la opción más común para columnas dinámicas, uniformemente espaciadas.
- Adaptive] – La cuadrícula determina automáticamente cuántos elementos caben por fila de columnas según un tamaño mínimo específico. Esta es la forma más simple de hacer un diseño dinámico que responda al ancho de pantalla.
Por ejemplo, para crear una cuadrícula que se ajuste automáticamente a tantas columnas como sea posible, cada una con un ancho mínimo de 100 puntos, escribiría:
let columns = [
GridItem(.adaptive(minimum: 100))
]
Esta línea única produce un diseño que se adapta de una columna en un iPhone estrecho a varias columnas en un iPad en el paisaje, exactamente el comportamiento que queremos para los diseños dinámicos.
Construyendo una cuadrilla dinámica básica
Empecemos con una red simple, totalmente dinámica usando el tamaño. A continuación se muestra una vista completa que muestra una serie de cadenas en una red receptiva:
struct AdaptiveGridView: View {
let items = Array(1...20).map { "Item \($0)" }
var body: some View {
ScrollView {
LazyVGrid(
columns: [GridItem(.adaptive(minimum: 80), spacing: 12)],
spacing: 12
) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(minWidth: 80, maxWidth: .infinity, minHeight: 80)
.background(Color.blue.opacity(0.2))
.cornerRadius(8)
}
}
.padding()
}
}
}
Aquí, cada artículo se ve obligado a por lo menos 80 puntos de ancho y alto. El artículo de la rejilla calcula automáticamente cuántos elementos pueden caber por hilera dada la anchura disponible, respetando la anchura mínima. El resultado es un diseño que rebosa sin problemas cuando el dispositivo gira o la ventana se redimensiona (en iPad o Mac).
Este enfoque funciona bien para el contenido simple, pero para más control que a menudo necesita combinar con artículos, o utilizar para calcular los recuentos de columnas personalizados.
Usando GeometríaReader para Conteos de Columna Dinámica Precisa
Mientras maneja muchos casos, a veces desea establecer un número exacto de columnas basadas en el ancho del contenedor – por ejemplo, siempre 2 columnas en un iPhone en retrato, 3 en paisaje y 4 en iPad. La vista GeometríaReader proporciona el tamaño actual de su padre, lo que le permite calcular el recuento óptimo de columna dinámicamente.
Ejemplo: Conteo de columna adaptativa
La siguiente vista lee el ancho disponible y calcula un recuento de columna basado en un ancho de artículo objetivo:
struct DynamicColumnGridView: View {
let items = Array(1...30).map { "Item \($0)" }
let targetItemWidth: CGFloat = 120
var columns: [GridItem] {
let count = max(Int(geometryProxy.size.width / targetItemWidth), 1)
return Array(repeating: GridItem(.flexible(), spacing: 12), count: count)
}
var body: some View {
GeometryReader { geometry in
ScrollView {
let width = geometry.size.width
let count = max(Int(width / targetItemWidth), 1)
let columns = Array(repeating: GridItem(.flexible(), spacing: 12), count: count)
LazyVGrid(columns: columns, spacing: 12) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 80)
.background(Color.green.opacity(0.3))
.cornerRadius(8)
}
}
.padding()
}
}
}
}
Importante: En la práctica, debe almacenar el valor dentro de una variable o utilizarlo dentro del mismo cierre. El ejemplo anterior utiliza una variable ayudante dentro del cierre para la claridad. Siempre asegúrese de que no envuelve todo el cuerpo en innecesariamente – puede romper el diseño si se utiliza como la vista superior.
Esta técnica le da control completo sobre el número de columnas manteniendo los elementos flexibles para que llenan el ancho uniformemente. También puede añadir restricciones mínimas y máximas a los elementos flexibles para evitar células extremadamente estiradas o aplastadas.
Adaptación dinámica de Row Heights
Los diseños dinámicos no son sólo sobre columnas – alturas de fila también pueden variar según el contenido. SwiftUI no proporciona una red directa de “aceleración automática” como UIKit con tamaños estimados. Sin embargo, puede lograr resultados similares utilizando el tamaño del contenido intrínseco y o incrustando alturas basadas en datos.
Por ejemplo, puede hacer que cada célula de la red sea auto-size omitiendo alturas explícitas y dejando que el contenido interno determine el tamaño. SwiftUI calculará automáticamente la altura de la célula basado en el elemento más alto en cada fila (para rejillas verticales). Pero si necesita alturas de fila verdaderamente variables (como un diseño de la mampostería), necesita un enfoque personalizado – a menudo utilizando
Manejo de grandes conjuntos de datos con perezoso carga
Una de las principales ventajas de y es su comportamiento de carga perezosa. Sólo crean vistas para los elementos que son actualmente visibles (más un pequeño búfer). Esto los hace eficientes para conjuntos de datos con cientos o incluso miles de artículos. Sin embargo, hay algunas mejores prácticas para mantener un rendimiento suave:
- Utilizar identificadores estables] – Siempre proporcionar un parámetro único a . Para estructurar modelos de datos que se conforman con , SwiftUI puede diferir eficientemente.
- Evitar computaciones costosas dentro del cuerpo] – Mantener las vistas de la célula simple. Si necesita cálculos complejos de diseño, precomputarlas fuera de la red.
- Leverage ] – Si su vista celular se ajusta a o utiliza el modificador , SwiftUI puede saltarse los cambios de renderizado cuando los datos de la célula no han cambiado.
- Use en un – Si anida un dentro de otro contenedor perezoso, puede romper la carga perezosa. Típicamente, la red misma debe ser el niño directo de un (o ser envuelto dentro de uno).
Combinando diseños dinámicos con animaciones
Las animaciones en SwiftUI pueden hacer que los cambios de diseño se sientan naturales y pulidos. Por ejemplo, cuando el número de columnas cambia (debido a la rotación o el tamaño de la ventana), puede animar los elementos de la red a sus nuevas posiciones. La manera más fácil es envolver la red en un modificador o utilizar el modificador con un valor que activa el cambio.
Cambios de columnas de imagen
Aquí hay una extensión del ejemplo de columna dinámica anterior con una transición animada:
struct AnimatedDynamicGridView: View {
let items = Array(1...20).map { "Item \($0)" }
@State private var targetItemWidth: CGFloat = 120
var body: some View {
GeometryReader { geometry in
ScrollView {
let width = geometry.size.width
let count = max(Int(width / targetItemWidth), 1)
let columns = Array(repeating: GridItem(.flexible(), spacing: 12), count: count)
LazyVGrid(columns: columns, spacing: 12) {
ForEach(items, id: \.self) { item in
Text(item)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 80)
.background(Color.orange.opacity(0.4))
.cornerRadius(8)
.transition(.scale.combined(with: .opacity))
}
}
.padding()
.animation(.spring(response: 0.4, dampingFraction: 0.7), value: count)
}
}
}
}
Al atar la animación al valor , SwiftUI animará la inserción, eliminación y reorganización de los elementos cuando el número de columnas cambie. También puede utilizar para transiciones más avanzadas entre los diseños.
Ejemplos prácticos: Diseños dinámicos en el mundo real
Caminemos por dos escenarios comunes que se benefician de los diseños dinámicos de vista de la colección.
Galería de fotos Grid
Una galería de fotos típica utiliza una cuadrícula de celda cuadrada que se adapta a la anchura de la pantalla. Quiere que las células sean lo más grandes posible mientras mantiene un número fijo de columnas (por ejemplo, 2 en iPhone, 3 en iPhone Plus, 4 en iPad). Usar con un recuento de columna condicional basado en las clases de tamaño es sencillo:
struct PhotoGalleryGrid: View {
let images: [String]
@Environment(\.horizontalSizeClass) var sizeClass
var columns: [GridItem] {
let count = sizeClass == .compact ? 2 : 4
return Array(repeating: GridItem(.flexible(), spacing: 2), count: count)
}
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 2) {
ForEach(images, id: \.self) { imageName in
Image(imageName)
.resizable()
.aspectRatio(1, contentMode: .fill)
.clipped()
}
}
.padding(.horizontal, 2)
}
}
}
Diámetro dinámico con tamaños de células variables
Para un panel de control, puede tener células de diferentes anchos – por ejemplo, un gráfico grande que toma dos columnas, estadísticas más pequeñas que toman una columna cada uno. Puede lograr esto combinando artículos con multiplicadores explícitos utilizando una matriz personalizada . Por ejemplo:
let columns: [GridItem] = [
GridItem(.flexible(minimum: 80), spacing: 12), // small stat cell
GridItem(.flexible(minimum: 160), spacing: 12), // wide cell
GridItem(.flexible(minimum: 80), spacing: 12) // small stat cell
]
Luego, en la red , puede mapear diferentes tipos de datos a diferentes lapsos de columna envolviendo elementos en un contenedor que se expande para llenar el ancho de la red. Esto requiere una coordinación cuidadosa porque no admite nativamente lapsos de varios cuartos. Un conjunto de trabajo común es utilizar modificador (disponible en iOS 16+) o dividir manualmente los datos de la rejilla
Para iOS 16 y más tarde, puede utilizar el modificador en una vista dentro de la cuadrícula para especificar cuántas columnas que la vista debe abarcar:
LazyVGrid(columns: columns, spacing: 12) {
ForEach(dashboardItems, id: \.id) { item in
DashboardCell(item: item)
.gridCellColumns(item.columnSpan)
}
}
Esta es la forma más limpia de crear un verdadero diseño dinámico de tableros de instrumentos con tamaños de celda mixtos.
Consideraciones de la ejecución para grandes conjuntos de datos
Cuando se trata de miles de artículos, incluso la carga perezosa puede llevar a la zaga si cada célula es compleja. Aquí están técnicas avanzadas para mantener sus rejillas dinámicas suaves:
- Prefetch images and data] – Use o para cargar datos de forma asincrónica, no en el cuerpo de la célula.
- Use para listas extremadamente grandes] – SwiftUI está más optimizado para miles de filas con tamaño dinámico. Sin embargo, para una distribución de la red, con una disposición personalizada es posible pero más difícil de lograr; considere utilizar vía [Fck]
- Recomputación de diseño – Evite poner lógica de diseño dinámico dentro del cuerpo de la célula. Geometrías precomputadas cuando sea posible.
- Use en toda la red] – Si cambias completamente la estructura de la red (por ejemplo, cambiando de 2 columnas a 3), asignando un nuevo a la red lo obligó a volver a cargar por completo, lo que puede ser más rápido que intentar animar un cambio complejo.
Recursos externos para profundizar su conocimiento
Para explorar más a fondo las opiniones dinámicas de la colección en SwiftUI, consulte estos recursos oficiales y comunitarios:
- Documentación LazyVGrid deApple – La referencia oficial para todos los parámetros y comportamientos. ]Aplicación Documentación para Desarrolladores: LazyVGrid
- Guía de inicio rápido para GridItem – Cubre las tres estrategias de tamaño con ejemplos interactivos. ]Aplicación Documentación para desarrolladores: GridItem
- SwiftUI by Ejemplo – Grid Layouts – Un tutorial práctico de Hacking con Swift que cubre las redes adaptables y flexibles.
- SwiftUI Lab: Lazy Grids – Inmersión profunda en el rendimiento y las personalizaciones. SwiftUI Lab: Lazy Grids
Resumen de las mejores prácticas
Crear una dinámica de diseño de vistas de la colección en SwiftUI requiere equilibrar la flexibilidad con el rendimiento. Aquí hay una lista de verificación rápida para las redes de producción:
- Comience con para el recuento de columnas dinámicas más simple; use solamente cuando necesite control preciso.
- Siempre proporcionar valores únicos o conformarse a .
- Use con un valor que cambie (como el recuento de columna) para transiciones suaves.
- Para tamaños de celda mixta, prefiera en iOS 16+ o diseñar un diseño personalizado de fila por fila.
- Perfile su rejilla con Instrumentos para verificar la carga perezosa está funcionando y las células no están renderizando contenido de pantalla.
- Prueba en múltiples tamaños y orientaciones de dispositivos – diseños dinámicos que se ven geniales en una pantalla puede romper en otra.
Dominar vistas dinámicas de la colección le permite crear aplicaciones que se sientan nativas y sensibles en cada dispositivo de Apple. Con las herramientas declarativas de SwiftUI, puede lograr lo que una vez requerido docenas de líneas de código UIKit en sólo un puñado de componentes expresivos y reutilizables.