Crear un diseño de flujo
Distribuya los elementos dinámicamente en varias líneas.
Crear un diseño de flujo es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Swift Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Swift Academy incluye 4 lecciones en total.
¿Qué es un layout de flujo?
Un layout de flujo coloca los elementos de izquierda a derecha y los ajusta en una fila nueva cuando el siguiente elemento desbordaría el ancho disponible, como ocurre con las etiquetas o el ajuste de palabras.
El plan
Calcularemos los saltos de fila en un helper compartido, devolveremos la altura total desde sizeThatFits y reutilizaremos el mismo cálculo en placeSubviews. Compartir la lógica mantiene la coherencia entre ambos métodos.
Modelar una colocación
Una estructura pequeña registra dónde se coloca cada subvista. Calcular todas las colocaciones por adelantado simplifica ambos métodos del protocolo.
struct Placement {
let index: Int
let point: CGPoint
let size: CGSize
}El algoritmo de ajuste
Recorra las subvistas y realice un seguimiento de la x actual. Si una vista secundaria superaría el ancho máximo, restablezca x y baje en una cantidad igual a la altura de la fila más el espaciado.
func layout(_ subviews: Subviews, maxWidth: CGFloat) -> (placements: [Placement], height: CGFloat) {
var placements: [Placement] = []
var x: CGFloat = 0, y: CGFloat = 0, rowHeight: CGFloat = 0
let spacing: CGFloat = 8
for (i, s) in subviews.enumerated() {
let size = s.sizeThatFits(.unspecified)
if x + size.width > maxWidth, x > 0 {
x = 0; y += rowHeight + spacing; rowHeight = 0
}
placements.append(Placement(index: i, point: CGPoint(x: x, y: y), size: size))
x += size.width + spacing
rowHeight = max(rowHeight, size.height)
}
return (placements, y + rowHeight)
}Implementar sizeThatFits
sizeThatFits ejecuta el algoritmo con el ancho propuesto y devuelve el ancho de la propuesta junto con la altura total calculada.
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let maxWidth = proposal.width ?? .infinity
let result = layout(subviews, maxWidth: maxWidth)
return CGSize(width: maxWidth == .infinity ? result.placements.map { $0.point.x + $0.size.width }.max() ?? 0 : maxWidth,
height: result.height)
}Implementar placeSubviews
placeSubviews ejecuta el mismo algoritmo, desplaza cada colocación según bounds.origin y llama a place.
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let result = layout(subviews, maxWidth: bounds.width)
for p in result.placements {
let pt = CGPoint(x: bounds.minX + p.point.x, y: bounds.minY + p.point.y)
subviews[p.index].place(at: pt, anchor: .topLeading,
proposal: ProposedViewSize(p.size))
}
}El tipo FlowLayout completo
Al combinar las piezas se obtiene un layout de flujo completo y reutilizable. El helper compartido layout garantiza que el tamaño y la colocación coincidan.
struct FlowLayout: Layout {
var spacing: CGFloat = 8
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let r = layout(subviews, maxWidth: proposal.width ?? .infinity)
return CGSize(width: proposal.width ?? 0, height: r.height)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let r = layout(subviews, maxWidth: bounds.width)
for p in r.placements {
subviews[p.index].place(at: CGPoint(x: bounds.minX + p.point.x, y: bounds.minY + p.point.y),
anchor: .topLeading, proposal: ProposedViewSize(p.size))
}
}
}Usar el layout de flujo
Incorpórelo como cualquier contenedor. Las etiquetas se ajustan automáticamente a medida que se reduce el ancho.
var body: some View {
FlowLayout {
ForEach(tags, id: \.self) { tag in
Text(tag)
.padding(8)
.background(.blue.opacity(0.2))
.clipShape(Capsule())
}
}
}Gestionar el primer elemento de cada fila
La condición x > 0 evita ajustar la primera fila antes de colocar su primer elemento. Sin ella, un elemento más ancho que el contenedor podría entrar en un bucle infinito o pasar innecesariamente a una fila vacía.
if x + size.width > maxWidth, x > 0 {
// wrap only if the row already has content
}Opciones de espaciado
Aquí el espaciado es una propiedad almacenada con un valor predeterminado. En producción, lea la preferencia de spacing de cada subvista para respetar las métricas del sistema en lugar de usar una constante fija.
var spacing: CGFloat = 8 // configurable per instanceProbar casos límite
Pruebe con cero elementos, un elemento enorme y muchos elementos pequeños. Un layout de flujo correcto indica una altura de cero para el contenido vacío y nunca recorta una única vista secundaria que sea demasiado grande.
Comprobación rápida: layout de flujo
Compruebe su comprensión del algoritmo de ajuste.
Resumen: crear un layout de flujo
Un layout de flujo ajusta los elementos realizando un seguimiento de la x acumulada y restableciéndola en una fila nueva cuando la siguiente vista secundaria desbordaría el espacio. Un helper compartido calcula todas las colocaciones y la altura total para que sizeThatFits y placeSubviews sean coherentes.
Desplace las colocaciones según bounds.origin, gestione el primer elemento de cada fila y pruebe los casos de contenido vacío, elementos demasiado grandes y muchos elementos. El resultado es un contenedor reutilizable con ajuste de elementos.
Preguntas frecuentes
¿La lección «Crear un diseño de flujo» es gratis?
Sí — el texto completo de «Crear un diseño de flujo» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Swift Academy, actualiza a CoddyKit PRO. El curso de Swift Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Crear un diseño de flujo»?
Distribuya los elementos dinámicamente en varias líneas. Practicas Swift Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Swift Academy?
No se requiere experiencia previa. Swift Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Crear un diseño de flujo»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Swift Academy?
Sí. Cada lección de Swift Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Fundamentos del protocolo Layout
- Medición de subvistas
- Crear un diseño de flujo
- Caché y rendimiento del diseño