Podstawy protokołu Layout
Implementowanie sizeThatFits i placeSubviews.
Podstawy protokołu Layout to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.
Po co tworzyć własny układ?
SwiftUI zawiera elementy HStack, VStack i ZStack, ale czasami potrzebna jest logika rozmieszczania, której nie da się w nich wyrazić — na przykład menu radialne, układy przepływowe lub siatki masonry.
Protokół Layout pozwala napisać taką logikę, zachowując możliwość komponowania ze zwykłymi widokami SwiftUI.
Protokół Layout
Protokół Layout wymaga dwóch metod: sizeThatFits (jak duży powinienem być?) oraz placeSubviews (gdzie umieścić każde dziecko?).
Spełniasz go dla typu wartości i używasz go tak jak każdego wbudowanego stosu.
struct MyLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize { .zero }
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) { }
}Używanie własnego układu
Wartość typu Layout działa jak kontener. Widoki potomne przekazuje się w jego domknięciu końcowym, dokładnie tak jak w przypadku stosu.
var body: some View {
MyLayout {
Text("One")
Text("Two")
Text("Three")
}
}ProposedViewSize
Rodzic przekazuje propozycję rozmiaru układowi za pośrednictwem ProposedViewSize. Jego właściwości width i height są opcjonalne: nil oznacza „nieokreślony, wybierz rozmiar idealny”.
Wartości specjalne .zero, .infinity i .unspecified służą do sprawdzania odpowiednio rozmiaru minimalnego, maksymalnego i idealnego.
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
let width = proposal.width ?? 0
return CGSize(width: width, height: 44)
}sizeThatFits szczegółowo
sizeThatFits zwraca rozmiar wybrany przez układ dla danej propozycji. SwiftUI może wywołać tę metodę wielokrotnie z różnymi propozycjami, aby określić elastyczność układu.
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)
}Kolekcja Subviews
Subviews to kolekcja proxy dla każdego elementu potomnego. Każde proxy odpowiada na sizeThatFits i udostępnia priorytety układu oraz wartości niestandardowe.
Nie uzyskujesz dostępu do rzeczywistych widoków — widzisz wyłącznie te proxy pomiarowe.
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
print(size)
}placeSubviews
placeSubviews przypisuje każdemu elementowi potomnemu pozycję wewnątrz przekazanego prostokąta bounds.
Wywołaj place(at:anchor:proposal:) na każdym proxy podwidoku.
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
}
}Punkty zakotwiczenia podczas rozmieszczania
Parametr anchor określa, który punkt elementu potomnego zostanie umieszczony w podanej pozycji. .topLeading pozycjonuje element względem jego lewego górnego rogu, a .center wyśrodkowuje go względem tej pozycji.
subview.place(at: CGPoint(x: 0, y: 0),
anchor: .topLeading,
proposal: .unspecified)Granice nie zawsze zaczynają się w początku układu
Prostokąt bounds może nie zaczynać się w punkcie (0,0). Zawsze pozycjonuj elementy względem bounds.minX i bounds.minY, nigdy względem bezwzględnego zera.
let startX = bounds.minX // not 0
let startY = bounds.minYMinimalny układ z równymi odstępami
Łącząc wszystko, otrzymujemy układ, który rozmieszcza elementy potomne od lewej do prawej bez odstępów. Obie metody pozostają spójne: zgłoszony rozmiar odpowiada rozmieszczeniu.
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
}
}
}Za spójność odpowiadasz Państwo
SwiftUI zakłada, że obie metody są ze sobą zgodne. Jeśli placeSubviews używa więcej miejsca, niż zgłoszono w sizeThatFits, elementy potomne mogą zostać przycięte lub nachodzić na siebie.
Współdziel obliczenia geometrii między obiema metodami.
Szybki sprawdzian: podstawy Layout
Sprawdź swoją znajomość protokołu Layout.
Podsumowanie: podstawy protokołu Layout
Protokół Layout przekształca niestandardową logikę rozmieszczania w kontener wielokrotnego użytku. sizeThatFits zgłasza rozmiar dla obiektu ProposedViewSize, a placeSubviews umieszcza każde proxy elementu potomnego wewnątrz bounds za pomocą place(at:anchor:proposal:).
Propozycje zawierają opcjonalne wymiary, granice mogą być przesunięte względem początku układu, a obie metody muszą zachowywać spójność geometryczną. Następnie szczegółowo zmierzymy podwidoki.
Często zadawane pytania
Czy lekcja „Podstawy protokołu Layout” jest bezpłatna?
Tak — pełny tekst „Podstawy protokołu Layout” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Podstawy protokołu Layout”?
Implementowanie sizeThatFits i placeSubviews. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Swift Academy?
Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Podstawy protokołu Layout”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?
Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy protokołu Layout
- Mierzenie podwidoków
- Budowanie układu przepływowego
- Pamięć podręczna układu i wydajność