Swift Academy · Lektion

Ein Flow-Layout erstellen

Verteilen Sie Elemente dynamisch auf mehrere Zeilen.

Lektion 3 von 413 Schritte

Ein Flow-Layout erstellen ist eine kostenlose Swift Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Swift Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Swift Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist ein Flow-Layout?

Ein Flow-Layout platziert Elemente von links nach rechts und beginnt eine neue Zeile, sobald das nächste Element die verfügbare Breite überschreiten würde – ähnlich wie bei Tag-Chips oder einem Zeilenumbruch in Text.

Der Plan

Wir berechnen die Zeilenumbrüche in einer gemeinsamen Hilfsmethode, geben die Gesamthöhe aus sizeThatFits zurück und verwenden dieselbe Berechnung in placeSubviews erneut. Durch die gemeinsame Logik bleiben beide Methoden konsistent.

Eine Platzierung modellieren

Eine kleine Struktur hält fest, wo jede Unteransicht platziert wird. Wenn alle Platzierungen im Voraus berechnet werden, bleiben beide Protokollmethoden unkompliziert.

struct Placement {
    let index: Int
    let point: CGPoint
    let size: CGSize
}

Der Umbruchalgorithmus

Durchlaufen Sie die Unteransichten und verfolgen Sie den aktuellen x-Wert. Wenn eine untergeordnete Ansicht die maximale Breite überschreiten würde, setzen Sie x zurück und gehen um die Zeilenhöhe plus Abstand nach unten.

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)
}

sizeThatFits implementieren

sizeThatFits führt den Algorithmus anhand der vorgeschlagenen Breite aus und gibt die vorgeschlagene Breite sowie die berechnete Gesamthöhe zurück.

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)
}

placeSubviews implementieren

placeSubviews führt denselben Algorithmus aus, verschiebt anschließend jede Platzierung um bounds.origin und ruft place auf.

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))
    }
}

Der vollständige Typ FlowLayout

Zusammen ergeben die einzelnen Teile ein vollständiges, wiederverwendbares Flow-Layout. Die gemeinsame Hilfsmethode layout stellt sicher, dass Größe und Platzierung übereinstimmen.

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))
        }
    }
}

Das Flow-Layout verwenden

Setzen Sie es wie jeden anderen Container ein. Die Tags werden automatisch umgebrochen, wenn die Breite kleiner wird.

var body: some View {
    FlowLayout {
        ForEach(tags, id: \.self) { tag in
            Text(tag)
                .padding(8)
                .background(.blue.opacity(0.2))
                .clipShape(Capsule())
        }
    }
}

Das erste Element jeder Zeile berücksichtigen

Die Bedingung x > 0 verhindert einen Umbruch vor dem ersten Element einer Zeile. Ohne sie könnte ein Element, das breiter als der Container ist, eine Endlosschleife verursachen oder unnötigerweise in eine leere Zeile verschoben werden.

if x + size.width > maxWidth, x > 0 {
    // wrap only if the row already has content
}

Abstände festlegen

Hier ist der Abstand eine gespeicherte Eigenschaft mit einem Standardwert. Lesen Sie im produktiven Einsatz die spacing-Präferenz jeder Unteransicht aus, um Systemmetriken zu berücksichtigen, statt eine feste Konstante zu verwenden.

var spacing: CGFloat = 8 // configurable per instance

Randfälle testen

Testen Sie mit null Elementen, einem einzelnen sehr großen Element und vielen sehr kleinen Elementen. Ein korrektes Flow-Layout meldet bei leerem Inhalt eine Höhe von null und schneidet niemals eine einzelne übergroße untergeordnete Ansicht ab.

Kurzer Test: Flow-Layout

Testen Sie Ihr Verständnis des Umbruchalgorithmus.

Zusammenfassung: Ein Flow-Layout erstellen

Ein Flow-Layout wickelt Elemente um, indem es den aktuellen x-Wert verfolgt und eine neue Zeile beginnt, sobald das nächste Element überlaufen würde. Eine gemeinsame Hilfsmethode berechnet alle Platzierungen und die Gesamthöhe, sodass sizeThatFits und placeSubviews konsistent bleiben.

Verschieben Sie Platzierungen um bounds.origin, berücksichtigen Sie das erste Element jeder Zeile und testen Sie leere, übergroße sowie umfangreiche Inhalte. Das Ergebnis ist ein wiederverwendbarer Container mit Zeilenumbruch.

Kostenlos starten

Lerne Swift mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
122
Lektionen
409

Häufig gestellte Fragen

Ist die Lektion „Ein Flow-Layout erstellen“ kostenlos?

Ja — der vollständige Text von „Ein Flow-Layout erstellen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Swift Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Swift Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Ein Flow-Layout erstellen“?

Verteilen Sie Elemente dynamisch auf mehrere Zeilen. Du übst Swift Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Swift Academy zu starten?

Keine Vorkenntnisse erforderlich. Swift Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Ein Flow-Layout erstellen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Swift Academy-Lektion Code schreiben und ausführen?

Ja. Jede Swift Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Grundlagen des Layout-Protocols
  2. Subviews messen
  3. Ein Flow-Layout erstellen
  4. Layout-Cache und Performance
← Zurück zu Swift Academy