Creazione di un flow layout
Disponi dinamicamente gli elementi su più righe.
Creazione di un flow layout è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.
Che cos'è un layout a flusso
Un layout a flusso dispone gli elementi da sinistra a destra, andando a capo quando l'elemento successivo supererebbe la larghezza disponibile, come accade con i tag o con il testo disposto su più righe.
Il piano
Calcoleremo le interruzioni di riga in un helper condiviso, restituiremo l'altezza totale da sizeThatFits e riutilizzeremo lo stesso calcolo in placeSubviews. Condividere la logica mantiene coerenti i due metodi.
Modellazione di un posizionamento
Una piccola struct registra la posizione di ogni sottovista. Calcolare in anticipo tutti i posizionamenti rende semplici entrambi i metodi del protocollo.
struct Placement {
let index: Int
let point: CGPoint
let size: CGSize
}L'algoritmo di disposizione su più righe
Scorra le sottoviste tenendo traccia della posizione x corrente. Se una vista figlia supererebbe la larghezza massima, reimposti x e scenda di un'altezza di riga più la spaziatura.
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)
}Implementazione di sizeThatFits
sizeThatFits esegue l'algoritmo in base alla larghezza proposta e restituisce la larghezza della proposta insieme all'altezza totale calcolata.
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)
}Implementazione di placeSubviews
placeSubviews esegue lo stesso algoritmo, quindi sposta ogni posizionamento di bounds.origin e chiama 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))
}
}Il tipo FlowLayout completo
Unendo i vari elementi si ottiene un layout a flusso completo e riutilizzabile. L'helper condiviso layout garantisce la coerenza tra dimensionamento e posizionamento.
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))
}
}
}Utilizzo del layout a flusso
Lo utilizzi come un qualsiasi contenitore. I tag andranno automaticamente a capo quando la larghezza diminuisce.
var body: some View {
FlowLayout {
ForEach(tags, id: \.self) { tag in
Text(tag)
.padding(8)
.background(.blue.opacity(0.2))
.clipShape(Capsule())
}
}
}Gestione del primo elemento di ogni riga
La condizione x > 0 impedisce di andare a capo prima del primo elemento di una riga. Senza di essa, un elemento più largo del contenitore potrebbe entrare in un ciclo infinito o essere spostato inutilmente in una riga vuota.
if x + size.width > maxWidth, x > 0 {
// wrap only if the row already has content
}Scelte per la spaziatura
Qui la spaziatura è una proprietà memorizzata con un valore predefinito. In produzione, legga la preferenza spacing di ogni sottovista per rispettare le metriche di sistema invece di usare una costante codificata.
var spacing: CGFloat = 8 // configurable per instanceTest dei casi limite
Esegua test con zero elementi, un solo elemento molto grande e molti elementi piccoli. Un layout a flusso corretto restituisce un'altezza pari a zero per i contenuti vuoti e non ritaglia mai una singola vista figlia troppo grande.
Verifica rapida: layout a flusso
Verifichi la Sua comprensione dell'algoritmo di disposizione su più righe.
Riepilogo: creazione di un layout a flusso
Un layout a flusso dispone gli elementi su più righe tenendo traccia della x corrente e passando a una nuova riga quando la vista figlia successiva supererebbe i limiti. Un helper condiviso calcola tutti i posizionamenti e l'altezza totale, mantenendo coerenti sizeThatFits e placeSubviews.
Sposti i posizionamenti di bounds.origin, gestisca il primo elemento di ogni riga e testi i casi con contenuto vuoto, elementi troppo grandi e molti elementi. Il risultato è un contenitore riutilizzabile con disposizione su più righe.
Domande Frequenti
La lezione «Creazione di un flow layout» è gratuita?
Sì — il testo completo di «Creazione di un flow layout» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.
Cosa imparerò in «Creazione di un flow layout»?
Disponi dinamicamente gli elementi su più righe. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Swift Academy?
Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Creazione di un flow layout»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Swift Academy?
Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Basi del protocollo Layout
- Misurazione delle subview
- Creazione di un flow layout
- Cache del layout e prestazioni