Auto Layout: co to jest, responsywny layout interfejsów iOS

Autor: IT Sectr Opublikowano: 2026-02-21 Czas czytania: 9 min

Auto Layout — system adaptacyjnego pozycjonowania elementów interfejsu od Apple, oparty na matematycznych ograniczeniach (constraints). Opracowany dla iOS 6 (2012), Auto Layout pozwala tworzyć interfejsy, które poprawnie wyświetlają się na wszystkich urządzeniach — od iPhone SE (4,7″) do iPad Pro (12,9″) i Dynamic Island. Według Apple WWDC Session 202 (2024), ponad 90% aplikacji w App Store używa Auto Layout lub jego deklaratywnej alternatywy — SwiftUI layout system. Constraints opisują zależności między elementami UI poprzez równania liniowe: view1.leading = view2.trailing + 8.

Najważniejsze

  • Auto Layout — system adaptacyjnego układu Apple poprzez matematyczne ograniczenia (constraints) dla wszystkich rozmiarów ekranów.
  • Constraints — równania liniowe postaci view1.attribute = multiplier × view2.attribute + constant, rozwiązywane algorytmem Cassowary.
  • UIStackView — kontener automatycznie zarządzający constraints dla zagnieżdżonych view (horizontal/vertical, alignment, distribution).
  • NSLayoutConstraint — programowe API do tworzenia ograniczeń w kodzie z aktywacją przez isActive = true.
  • Safe Area i Layout Margins — wbudowane marginesy Auto Layout, zapobiegające nakładaniu się z Dynamic Island, Notch i Home Indicator.

Co to jest Auto Layout?

Auto Layout — to system adaptacyjnego układu Apple, wykorzystujący matematyczne ograniczenia (constraints) do pozycjonowania elementów UI. W przeciwieństwie do układu ramkowego (frame-based layout), gdzie każdy element ma stałe współrzędne x, y, width, height, Auto Layout opisuje relacje między elementami: «przycisk znajduje się 8pt od prawej krawędzi rodzica» lub «szerokość pola tekstowego jest równa połowie szerokości ekranu». Mechanizm oparty jest na algorytmie Cassowary, opracowanym na University of Washington (Greg J. Badros, 1999) i wdrożonym przez Apple w iOS 6. Cassowary rozwiązuje system nierówności liniowych z priorytetami — Required (1000), Default High (750), Default Low (250) — co pozwala zarządzać konfliktami ograniczeń. Auto Layout obsługuje trzy typy rozmiarów: intrinsic (naturalny rozmiar elementu określany przez treść), explicit (jawnie określone constraint) i compressible/stretchable (elastyczny tryb przez Content Hugging Priority i Compression Resistance Priority).

Intrinsic Content Size i Priorytety

Każdy element UI w Auto Layout ma Intrinsic Content Size — naturalny rozmiar określany przez jego zawartość. Dla UILabel zależy to od tekstu i czcionki, dla UIImageView — od rozmiarów obrazu. Content Hugging Priority (opór przed rozciąganiem) i Compression Resistance Priority (opór przed ściskaniem) zarządzają zachowaniem elementu przy zmianie dostępnego miejsca. Standardowe wartości: 251 dla hugging i 749 dla compression resistance. Jeśli dwa elementy konkurują o miejsce, priorytet określa, który rozciągnie się pierwszy. Zrozumienie tych priorytetów jest kluczem do eliminacji Ambiguous Layout (niejednoznacznego układu), który Xcode podświetla w debuggerze.

Anatomia Constraint

Constraint opisuje równanie: view1.attribute = multiplier × view2.attribute + constant. Atrybuty obejmują leading, trailing, top, bottom, centerX, centerY, width, height, firstBaseline, lastBaseline. Multiplier jest używany do relacji proporcjonalnych (szerokość view1 = 0,5 × szerokość superview). Constant określa stały odstęp (leading = superview.leading + 16). Narzędzia Interface Builder pozwalają określać constraints wizualnie przez Ctrl-przeciąganie, ale złożone układy wymagają programowego tworzenia przez NSLayoutConstraint lub VFL (Visual Format Language), który Apple zaleca zastępować na NSLayoutConstraint od iOS 9.

Jak działają Constraints w iOS

System constraints jest rozwiązywany jako zadanie programowania liniowego: algorytm Cassowary znajduje optymalne rozmieszczenie wszystkich elementów, spełniające wszystkie ograniczenia z uwzględnieniem ich priorytetów. Jeśli constraints są ze sobą sprzeczne, powstaje Unsatisfiable Layout — wyjątek, który Xcode loguje ze szczegółowym opisem konfliktu. Jeśli constraints jest niewystarczająco do określenia pozycji choć jednego elementu, powstaje Ambiguous Layout — elementy wyświetlają się w dowolnej pozycji. Apple zaleca minimalny zestaw: dla każdego elementu muszą być określone position (x, y) i size (width, height) — jawnie lub przez intrinsic content size. Constraints mogą być first-class: element wiodący (np. superview) i podrzędny (widok potomny) tworzą hierarchię.

Algorytm Cassowary i priorytety

Cassowary używa metody Sequential Quadratic Programming do rozwiązywania układów nierówności liniowych. Każdy constraint ma priorytet od 1 do 1000. Required (1000) — obowiązkowe ograniczenie; jeśli nie można go spełnić, aplikacja ulega awarii z NSConstraintException. Default High (750) — zalecane; Default Low (250) — najmniej ważne. W przypadku konfliktu Cassowary rozluźnia ograniczenia o niższym priorytecie. Na przykład, jeśli dwa elementy wymagają stałej szerokości, a ekran jest zbyt wąski, rozluźniane jest constraint o niższym priorytecie. W Xcode Debug View Hierarchy (narzędzie debugowania dostępne od Xcode 6) podświetla tylko problemy z Required constraints — pozostałe są obsługiwane bez błędu.

UIStackView: automatyczne zarządzanie Constraints

UIStackView — kontener przedstawiony w iOS 9 (2015), który automatycznie tworzy i zarządza constraints dla zagnieżdżonych arrangedSubviews. UIStackView obsługuje dwie osie: horizontal (układ poziomy) i vertical (pionowy). Ustawienia distribution określają rozkład miejsca: fill (wypełnienie proporcjonalne do hugging priority), fillEqually (równe rozmiary), fillProportionally (proporcjonalnie do intrinsic content size), equalSpacing (równe odstępy), equalCentering (równe odległości między środkami). Alignment określa wyrównanie w poprzek osi: fill, leading, center, trailing (dla horizontal) lub fill, top, center, bottom (dla vertical). UIStackView automatycznie zarządza spacing, baseline alignment i adaptacją do Dynamic Type.

swift
import UIKit

class StackViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let stack = UIStackView()
        stack.axis = NSLayoutConstraint.Axis.vertical
        stack.distribution = .fillEqually
        stack.spacing = 8
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        let label = UILabel()
        label.text = "Przewodnik Auto Layout"
        label.font = UIFont.preferredFont(forTextStyle: .headline)
        
        let button = UIButton(type: .system)
        button.setTitle("Zastosuj", for: .normal)
        
        stack.addArrangedSubview(label)
        stack.addArrangedSubview(button)
        view.addSubview(stack)
        
        NSLayoutConstraint.activate([
            stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            stack.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 16),
            stack.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -16)
        ])
    }
}

Kod tworzy pionowy UIStackView z dwoma elementami (UILabel i UIButton), rozmieszczonymi równomiernie (fillEqually) z odstępem 8pt. Stack jest wyśrodkowany na ekranie z odstępami od krawędzi co najmniej 16pt. translatesAutoresizingMaskIntoConstraints = false jest obowiązkowy przy programowym tworzeniu constraints — bez niego Auto Layout nie działa. W IT Sectr UIStackView jest używany w 80% ekranów projektów iOS do budowy adaptacyjnych formularzy, list ustawień i kart.

Zagnieżdżone Stack View

UIStackView mogą być zagnieżdżone: poziomy stos wewnątrz pionowego — standardowy wzorzec dla złożonych układów. Zewnętrzny stos zarządza wierszami, wewnętrzny — kolumnami wewnątrz wiersza. Kombinacja axis, alignment i distribution na każdym poziomie daje praktycznie nieograniczoną elastyczność bez ani jednego ręcznego constraint. Apple zaleca używanie UIStackView jako głównego narzędzia układu w UIKit, sięgając po ręczne NSLayoutConstraint tylko w przypadkach nieobjętych stosem: nakładające się view, precyzyjne pozycjonowanie w pikselach, niestandardowa animacja bounds.

NSLayoutConstraint: programowe tworzenie ograniczeń

NSLayoutConstraint — programowe API do tworzenia pojedynczych ograniczeń w kodzie. Każde constraint jest tworzone przez inicjalizator z parametrami: item, attribute, relatedBy, toItem, attribute, multiplier, constant. Od iOS 9 Apple przedstawiło Anchor API — bardziej czytelną składnię przez właściwości view.leadingAnchor, view.trailingAnchor, view.topAnchor, view.bottomAnchor, view.centerXAnchor, view.centerYAnchor, view.widthAnchor, view.heightAnchor. Anchor API automatycznie ustawia relatedBy = .equal i używa First Item/Second Item z Anchor, skracając kod o 40% w porównaniu z klasycznym NSLayoutConstraint.

swift
import UIKit

class ConstraintViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let childView = UIView()
        childView.backgroundColor = .systemBlue
        childView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(childView)
        
        NSLayoutConstraint.activate([
            childView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 24),
            childView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            childView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            childView.heightAnchor.constraint(equalToConstant: 120),
            childView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor, constant: -24)
        ])
    }
}

Kod pozycjonuje childView z odstępami od safeAreaLayoutGuide (top) i krawędzi ekranu (leading/trailing). lessThanOrEqualTo dla bottom gwarantuje, że view nie wyjdzie poza dolną granicę. Anchor API zgłasza wyjątek na etapie kompilacji, jeśli anchory są niekompatybilne (np. leadingAnchor miesza się z rightAnchor), co zapobiega błędom runtime. Apple zaleca Anchor API jako standard dla programowego Auto Layout od iOS 9.

Safe Area i Layout Margins w Auto Layout

Safe Area — obszar ekranu nieprzykrywany przez elementy systemowe: Dynamic Island, Notch, Status Bar, Home Indicator, zaokrąglone rogi. W iOS 11 Apple zastąpiło topLayoutGuide/bottomLayoutGuide na safeAreaLayoutGuide, który automatycznie dostosowuje się do orientacji urządzenia i obecności wycięcia ekranu. Layout Margins — wewnętrzne marginesy view domyślnie (16pt na iOS, 20pt na iPadOS). Dla UILayoutGuide można ustawić niestandardowe directionalLayoutMargins z uwzględnieniem lokalizacji RIGHT-TO-LEFT. Auto Layout automatycznie uwzględnia safe area przy użyciu safeAreaLayoutGuide w anchors.

Adaptacja do Dynamic Island i Notch

Na urządzeniach z Dynamic Island (iPhone 14 Pro i nowsze) i Notch (iPhone X–13) Safe Area wyklucza 44pt od góry w orientacji pionowej (59pt z Dynamic Island w stanie aktywnym). Home Indicator dodaje 34pt od dołu. Dla prawidłowej adaptacji wszystkie top-constraints powinny być powiązane z safeAreaLayoutGuide.topAnchor, a nie z view.topAnchor. Bottom-constraints — z safeAreaLayoutGuide.bottomAnchor lub view.bottomAnchor z zapasem na Home Indicator. W IT Sectr testujemy wszystkie ekrany na symulatorach iPhone SE (2022), iPhone 14 Pro Max i iPad Pro 12,9″ — trzech urządzeniach pokrywających wszystkie warianty safe area.

Typowe błędy Auto Layout

Najczęstsze błędy przy pracy z Auto Layout: zapomniane translatesAutoresizingMaskIntoConstraints = false, konfliktujące Required constraints (priorytet 1000), Ambiguous Layout (niewystarczająca liczba constraints do określenia pozycji), nieprawidłowy Content Hugging Priority dla UILabel z wieloliniowym tekstem i mieszanie leading/trailing z left/right anchors. Xcode 15+ wyświetla problemy układu w Runtime Issue Navigator i oferuje automatyczne poprawki. W przypadku złożonych układów używaj Debug View Hierarchy: żółte znaczniki wskazują ambiguous layout, czerwone — unsatisfiable.

BłądPrzyczynaRozwiązanie
translatesAutoresizingMaskIntoConstraints = trueAuto Layout nie jest aktywowany dla viewUstaw false dla wszystkich programowych view
Unsatisfiable LayoutKonflikt Required (1000) constraintsObniż priorytet jednego do Default High (750)
Ambiguous LayoutNiewystarczająca liczba constraints dla x/y/w/hDodaj brakujące constraint lub sprawdź intrinsic size
Obcinanie tekstu w UILabelContent Hugging Priority niższy niż u konkurentaPodnieś hugging priority do 252+
Mieszanie anchorów LTR/RTLleadingAnchor z rightAnchorUżywaj tylko leading/trailing dla obsługi RTL

Często zadawane pytania

Czym Auto Layout różni się od układu ramkowego?

Układ ramkowy określa stałe współrzędne x, y, width, height dla każdego elementu. Auto Layout używa matematycznych ograniczeń (constraints) — relacji między elementami: «label.leading = button.trailing + 8». Układ ramkowy nie dostosowuje się do rozmiaru ekranu; Auto Layout automatycznie przelicza pozycje przy obrocie, Split View lub zmianie Dynamic Type.

Kiedy należy używać UIStackView zamiast NSLayoutConstraint?

UIStackView jest optymalny dla układów liniowych: wiersze, kolumny, formularze, listy parametrów. NSLayoutConstraint jest niezbędny dla nakładających się view, precyzyjnego pozycjonowania pikseli, niestandardowej animacji bounds i przypadków, gdy rozkład miejsca jest nierównomierny i nie jest pokrywany przez distribution UIStackView. W praktyce 80% układów rozwiązuje UIStackView, 20% — ręczne constraints.

Co to jest Content Hugging Priority w Auto Layout?

Content Hugging Priority (opór przed rozciąganiem) — priorytet określający, jak bardzo element opiera się zwiększeniu swojego rozmiaru powyżej Intrinsic Content Size. Wartość domyślna — 251. Jeśli dwa elementy konkurują o wolne miejsce, element z wyższym hugging priority pozostanie swojego rozmiaru, a drugi się rozciągnie. Compression Resistance Priority (749 domyślnie) działa analogicznie dla ściskania.

Jak Auto Layout współpracuje z Dynamic Type?

Auto Layout automatycznie dostosowuje się do Dynamic Type, jeśli constraints używają intrinsic content size etykiet. Przy zwiększeniu rozmiaru czcionki UILabel rozszerza się, przesuwając sąsiednie elementy przez constraints. UIStackView z distribution = fillProportionally redystrybuuje miejsce proporcjonalnie do nowych intrinsic size. Safe Area i Layout Margins również uwzględniają ustawienia dostępności.

Dlaczego powstaje Unsatisfiable Layout?

Unsatisfiable Layout powstaje, gdy dwa Required (priority = 1000) constraints są ze sobą sprzeczne: na przykład view.leading = superview.leading + 16 i view.trailing = superview.leading + 200 przy superview o szerokości 100pt. Algorytm Cassowary nie może znaleźć rozwiązania, a aplikacja ulega awarii z NSConstraintException. Rozwiązanie — obniżyć priorytet jednego z konfliktujących constraints do Default High (750).

Podsumowanie

  • Auto Layout — system adaptacyjnego układu Apple oparty na algorytmie Cassowary, rozwiązującym układ ograniczeń liniowych z priorytetami.
  • Constraints — równania postaci view1.attribute = multiplier × view2.attribute + constant z priorytetami od 1 do 1000 (Required).
  • UIStackView — kontener automatycznie zarządzający constraints dla arrangedSubviews z obsługą osi, distribution i alignment.
  • NSLayoutConstraint z Anchor API — standard programowy od iOS 9, skracający kod o 40% w porównaniu z klasycznym API.
  • Safe Area — obszar bez Dynamic Island, Notch, Home Indicator; obowiązkowy do wiązania top/bottom constraints.
  • Typowe błędy — zapomniane translatesAutoresizingMaskIntoConstraints, konflikt Required, Ambiguous Layout, mieszanie anchorów LTR/RTL.
  • Intrinsic Content Size i priorytety (hugging 251, compression 749) zarządzają zachowaniem elementów przy zmianie dostępnego miejsca.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również