0Pricing
Swift Academy · Lektion

Grundlagen des Layout-Protocols

Implementieren Sie sizeThatFits und placeSubviews.

Grundlagen des Layout-Protocols ist eine kostenlose Swift Academy-Lektion auf CoddyKit. Dies ist Lektion 1 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.

Warum ein eigenes Layout?

SwiftUI wird mit HStack, VStack und ZStack ausgeliefert. Manchmal benötigen Sie jedoch eine Anordnungslogik, die diese nicht ausdrücken können – etwa radiale Menüs, Flow-Layouts oder Masonry-Grids.

Mit dem Layout-Protokoll können Sie diese Logik schreiben und sie trotzdem mit normalen SwiftUI-Views kombinieren.

Das Layout-Protokoll

Layout erfordert zwei Methoden: sizeThatFits (wie groß soll ich sein?) und placeSubviews (wo wird jedes untergeordnete Element platziert?).

Sie implementieren die Konformität für einen Werttyp und verwenden ihn wie jeden integrierten Stack.

struct MyLayout: Layout {
    func sizeThatFits(proposal: ProposedViewSize,
                      subviews: Subviews,
                      cache: inout ()) -> CGSize { .zero }
    func placeSubviews(in bounds: CGRect,
                       proposal: ProposedViewSize,
                       subviews: Subviews,
                       cache: inout ()) { }
}

Ein eigenes Layout verwenden

Ein Layout-Wert fungiert als Container. Sie übergeben ihm untergeordnete Views in einer trailing closure – genau wie bei einem Stack.

var body: some View {
    MyLayout {
        Text("One")
        Text("Two")
        Text("Three")
    }
}

ProposedViewSize

Der übergeordnete View schlägt Ihrem Layout über ProposedViewSize eine Größe vor. width und height sind optional: nil bedeutet „nicht angegeben, wählen Sie die optimale Größe“.

Die speziellen Werte .zero, .infinity und .unspecified prüfen die minimale, maximale und optimale Größe.

func sizeThatFits(proposal: ProposedViewSize,
                  subviews: Subviews,
                  cache: inout ()) -> CGSize {
    let width = proposal.width ?? 0
    return CGSize(width: width, height: 44)
}

sizeThatFits im Detail

sizeThatFits gibt die von Ihrem Layout gewünschte Größe für einen bestimmten Vorschlag zurück. SwiftUI kann die Methode mehrmals mit unterschiedlichen Vorschlägen aufrufen, um die Anpassungsfähigkeit Ihres Layouts zu ermitteln.

func sizeThatFits(proposal: ProposedViewSize,
                  subviews: Subviews,
                  cache: inout ()) -> CGSize {
    // Sum child ideal sizes for a simple horizontal stack
    let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
    let w = sizes.reduce(0) { $0 + $1.width }
    let h = sizes.map(\.height).max() ?? 0
    return CGSize(width: w, height: h)
}

Die Subviews-Auflistung

Subviews ist eine Auflistung von Proxys für jedes untergeordnete Element. Jeder Proxy beantwortet sizeThatFits und stellt Layout-Prioritäten sowie benutzerdefinierte Werte bereit.

Sie sehen niemals die tatsächlichen Views, sondern nur diese Messungs-Proxys.

for subview in subviews {
    let size = subview.sizeThatFits(.unspecified)
    print(size)
}

placeSubviews

placeSubviews weist jedem untergeordneten Element eine Position innerhalb des übergebenen bounds-Rechtecks zu.

Rufen Sie für jeden Subview-Proxy place(at:anchor:proposal:) auf.

func placeSubviews(in bounds: CGRect,
                   proposal: ProposedViewSize,
                   subviews: Subviews,
                   cache: inout ()) {
    var x = bounds.minX
    for subview in subviews {
        let size = subview.sizeThatFits(.unspecified)
        subview.place(at: CGPoint(x: x, y: bounds.midY),
                      anchor: .leading,
                      proposal: .unspecified)
        x += size.width
    }
}

Anker beim Platzieren

Der Parameter anchor legt fest, welcher Punkt des untergeordneten Elements auf der angegebenen Position liegt. .topLeading positioniert das Element anhand der oberen linken Ecke; .center zentriert es auf diesem Punkt.

subview.place(at: CGPoint(x: 0, y: 0),
              anchor: .topLeading,
              proposal: .unspecified)

Bounds liegen nicht immer am Ursprung

Das bounds-Rechteck beginnt möglicherweise nicht bei (0,0). Positionieren Sie immer relativ zu bounds.minX und bounds.minY, niemals relativ zum absoluten Nullpunkt.

let startX = bounds.minX // not 0
let startY = bounds.minY

Ein minimales Layout mit gleichen Abständen

Hier ist ein Layout, das die untergeordneten Elemente ohne Abstand von links nach rechts anordnet. Die beiden Methoden bleiben konsistent: Die gemeldete Größe entspricht der Platzierung.

struct SimpleHStack: Layout {
    func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
        let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
        return CGSize(width: sizes.reduce(0){ $0 + $1.width },
                      height: sizes.map(\.height).max() ?? 0)
    }
    func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
        var x = bounds.minX
        for s in subviews {
            let size = s.sizeThatFits(.unspecified)
            s.place(at: CGPoint(x: x, y: bounds.minY), anchor: .topLeading, proposal: .unspecified)
            x += size.width
        }
    }
}

Konsistenz ist Ihre Aufgabe

SwiftUI verlässt sich darauf, dass Ihre beiden Methoden übereinstimmen. Wenn placeSubviews mehr Platz verwendet, als sizeThatFits gemeldet hat, können untergeordnete Elemente abgeschnitten werden oder sich überlappen.

Verwenden Sie in beiden Methoden dieselben Geometrieberechnungen.

Schnelltest: Layout-Grundlagen

Testen Sie Ihr Verständnis des Layout-Protokolls.

Zusammenfassung: Grundlagen des Layout-Protokolls

Das Layout-Protokoll macht benutzerdefinierte Anordnungslogik zu einem wiederverwendbaren Container. sizeThatFits meldet Ihre Größe für einen ProposedViewSize, und placeSubviews positioniert jeden Proxy eines untergeordneten Elements innerhalb von bounds mithilfe von place(at:anchor:proposal:).

Vorschläge enthalten optionale Abmessungen, Bounds können vom Ursprung versetzt sein, und die beiden Methoden müssen geometrisch konsistent bleiben. Als Nächstes messen wir Subviews ausführlicher.

Häufig gestellte Fragen

Ist die Lektion „Grundlagen des Layout-Protocols“ kostenlos?

Ja — der vollständige Text von „Grundlagen des Layout-Protocols“ 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 „Grundlagen des Layout-Protocols“?

Implementieren Sie sizeThatFits und placeSubviews. 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 1 von 4.

Wie lange dauert die Lektion „Grundlagen des Layout-Protocols“?

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