Auto Layout — een systeem voor adaptieve positionering van interface-elementen van Apple, gebaseerd op wiskundige beperkingen (constraints). Ontwikkeld voor iOS 6 (2012), stelt Auto Layout je in staat interfaces te maken die correct worden weergegeven op alle apparaten — van iPhone SE (4.7″) tot iPad Pro (12.9″) en Dynamic Island. Volgens Apple WWDC Session 202 (2024) gebruikt meer dan 90% van de apps in de App Store Auto Layout of het declaratieve alternatief — SwiftUI layout system. Constraints beschrijven afhankelijkheden tussen UI-elementen via lineaire vergelijkingen: view1.leading = view2.trailing + 8.
Belangrijkste
Auto Layout — is Apple's adaptieve lay-outsysteem dat wiskundige beperkingen (constraints) gebruikt voor het positioneren van UI-elementen. In tegenstelling tot frame-based lay-out, waarbij elk element vaste coördinaten x, y, width, height heeft, beschrijft Auto Layout de relaties tussen elementen: «de knop bevindt zich op 8pt van de rechterrand van de ouder» of «de breedte van het tekstveld is gelijk aan de helft van de schermbreedte». Het mechanisme is gebaseerd op het Cassowary-algoritme, ontwikkeld aan de University of Washington (Greg J. Badros, 1999) en geïmplementeerd door Apple in iOS 6. Cassowary lost een systeem van lineaire ongelijkheden met prioriteiten op — Required (1000), Default High (750), Default Low (250) — wat het mogelijk maakt conflicten tussen beperkingen te beheren. Auto Layout ondersteunt drie typen afmetingen: intrinsic (natuurlijke grootte van het element bepaald door inhoud), explicit (expliciet opgegeven constraint) en compressible/stretchable (elastische modus via Content Hugging Priority en Compression Resistance Priority).
Elk UI-element in Auto Layout heeft een Intrinsic Content Size — de natuurlijke grootte bepaald door de inhoud. Voor UILabel hangt dit af van de tekst en het lettertype, voor UIImageView — van de afbeeldingsafmetingen. Content Hugging Priority (weerstand tegen uitrekken) en Compression Resistance Priority (weerstand tegen samendrukken) beheren het gedrag van het element bij verandering van beschikbare ruimte. Standaardwaarden: 251 voor hugging en 749 voor compression resistance. Als twee elementen concurreren om ruimte, bepaalt de prioriteit welke als eerste wordt uitgerekt. Begrip van deze prioriteiten is de sleutel tot het oplossen van Ambiguous Layout (dubbelzinnige lay-out), die Xcode markeert in de debugger.
Een constraint wordt beschreven door een vergelijking: view1.attribute = multiplier × view2.attribute + constant. Attributen omvatten leading, trailing, top, bottom, centerX, centerY, width, height, firstBaseline, lastBaseline. Multiplier wordt gebruikt voor proportionele relaties (breedte view1 = 0.5 × breedte superview). Constant definieert een vaste afstand (leading = superview.leading + 16). Interface Builder-tools maken het mogelijk constraints visueel in te stellen via Ctrl-slepen, maar complexe lay-outs vereisen programmatische creatie via NSLayoutConstraint of VFL (Visual Format Language), die Apple adviseert te vervangen door NSLayoutConstraint vanaf iOS 9.
Het constraints-systeem wordt opgelost als een lineair programmeringsprobleem: het Cassowary-algoritme vindt de optimale positionering van alle elementen, waarbij alle beperkingen worden nageleefd met inachtneming van hun prioriteiten. Als constraints elkaar tegenspreken, ontstaat Unsatisfiable Layout — een uitzondering die Xcode logt met een gedetailleerde beschrijving van het conflict. Als constraints onvoldoende zijn om de positie van ten minste één element te bepalen, ontstaat Ambiguous Layout — elementen worden op een willekeurige positie weergegeven. Apple beveelt een minimale set aan: voor elk element moeten position (x, y) en size (width, height) worden gespecificeerd — expliciet of via intrinsic content size. Constraints kunnen first-class zijn: het leidende element (bijv. superview) en het afhankelijke (kind-view) creëren een hiërarchie.
Cassowary gebruikt de Sequential Quadratic Programming-methode voor het oplossen van systemen van lineaire ongelijkheden. Elke constraint heeft een prioriteit van 1 tot 1000. Required (1000) — verplichte beperking; als deze niet kan worden vervuld, crasht de app met NSConstraintException. Default High (750) — aanbevolen; Default Low (250) — minst belangrijk. Bij een conflict versoepelt Cassowary beperkingen met een lagere prioriteit. Als bijvoorbeeld twee elementen een vaste breedte vereisen en het scherm is te smal, wordt de constraint met de lagere prioriteit versoepeld. In Xcode Debug View Hierarchy (debugtool beschikbaar sinds Xcode 6) worden alleen problemen met Required constraints gemarkeerd — de rest wordt zonder fout verwerkt.
UIStackView — een container geïntroduceerd in iOS 9 (2015), die automatisch constraints maakt en beheert voor geneste arrangedSubviews. UIStackView ondersteunt twee assen: horizontal (horizontale lay-out) en vertical (verticale). Distribution-instellingen bepalen de ruimteverdeling: fill (vulling evenredig aan hugging priority), fillEqually (gelijke afmetingen), fillProportionally (evenredig aan intrinsic content size), equalSpacing (gelijke tussenruimtes), equalCentering (gelijke afstanden tussen middelpunten). Alignment specificeert de uitlijning dwars op de as: fill, leading, center, trailing (voor horizontal) of fill, top, center, bottom (voor vertical). UIStackView beheert automatisch spacing, baseline alignment en aanpassing aan Dynamic Type.
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 = "Auto Layout-gids"
label.font = UIFont.preferredFont(forTextStyle: .headline)
let button = UIButton(type: .system)
button.setTitle("Toepassen", 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)
])
}
}De code maakt een verticale UIStackView met twee elementen (UILabel en UIButton), gelijkmatig verdeeld (fillEqually) met een tussenruimte van 8pt. De stack wordt gecentreerd op het scherm met marges van minimaal 16pt. translatesAutoresizingMaskIntoConstraints = false is verplicht bij het programmatisch maken van constraints — zonder werkt Auto Layout niet. Bij IT Sectr wordt UIStackView gebruikt in 80% van de iOS-projectschermen voor het bouwen van adaptieve formulieren, instellingslijsten en kaarten.
UIStackViews kunnen worden genest: horizontale stack binnen een verticale — een standaardpatroon voor complexe lay-outs. De buitenste stack beheert rijen, de binnenste — kolommen binnen een rij. De combinatie van axis, alignment en distribution op elk niveau biedt vrijwel onbeperkte flexibiliteit zonder één handmatige constraint. Apple raadt aan UIStackView te gebruiken als het primaire lay-outinstrument in UIKit, en alleen handmatige NSLayoutConstraint te gebruiken voor gevallen die niet door de stack worden gedekt: overlappende views, pixel-nauwkeurige positionering, aangepaste bounds-animatie.
NSLayoutConstraint — programmeer-API voor het maken van individuele beperkingen in code. Elke constraint wordt gemaakt via een initialisator met parameters: item, attribute, relatedBy, toItem, attribute, multiplier, constant. Vanaf iOS 9 introduceerde Apple de Anchor API — een leesbaardere syntax via de eigenschappen view.leadingAnchor, view.trailingAnchor, view.topAnchor, view.bottomAnchor, view.centerXAnchor, view.centerYAnchor, view.widthAnchor, view.heightAnchor. De Anchor API stelt automatisch relatedBy = .equal in en gebruikt First Item/Second Item uit Anchor, waardoor de code met 40% wordt verminderd in vergelijking met klassieke NSLayoutConstraint.
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)
])
}
}De code positioneert childView met margins van safeAreaLayoutGuide (top) en schermranden (leading/trailing). lessThanOrEqualTo voor bottom garandeert dat de view de ondergrens niet overschrijdt. De Anchor API gooit een uitzondering in de compilatiefase als anchors incompatibel zijn (bijv. leadingAnchor wordt gemengd met rightAnchor), wat runtime-fouten voorkomt. Apple beveelt de Anchor API aan als standaard voor programmatische Auto Layout vanaf iOS 9.
Safe Area — het schermgebied dat niet wordt bedekt door systeemelementen: Dynamic Island, Notch, Status Bar, Home Indicator, afgeronde hoeken. In iOS 11 verving Apple topLayoutGuide/bottomLayoutGuide door safeAreaLayoutGuide, die zich automatisch aanpast aan de oriëntatie van het apparaat en de aanwezigheid van een schermuitsparing. Layout Margins — standaard interne marges van een view (16pt op iOS, 20pt op iPadOS). Voor UILayoutGuide kunnen aangepaste directionalLayoutMargins worden ingesteld, rekening houdend met RIGHT-TO-LEFT-lokalisatie. Auto Layout houdt automatisch rekening met de safe area bij gebruik van safeAreaLayoutGuide in anchors.
Op apparaten met Dynamic Island (iPhone 14 Pro en nieuwer) en Notch (iPhone X–13) sluit Safe Area 44pt van boven uit in portret (59pt met Dynamic Island in actieve toestand). Home Indicator voegt 34pt van onderen toe. Voor correcte aanpassing moeten alle top-constraints worden gekoppeld aan safeAreaLayoutGuide.topAnchor, niet aan view.topAnchor. Bottom-constraints — aan safeAreaLayoutGuide.bottomAnchor of view.bottomAnchor met reserve voor Home Indicator. Bij IT Sectr testen we alle schermen op simulatoren van iPhone SE (2022), iPhone 14 Pro Max en iPad Pro 12.9″ — drie apparaten die alle varianten van safe area dekken.
De meest voorkomende fouten bij het werken met Auto Layout: vergeten translatesAutoresizingMaskIntoConstraints = false, conflicterende Required constraints (prioriteit 1000), Ambiguous Layout (onvoldoende constraints om positie te bepalen), onjuiste Content Hugging Priority voor UILabel met meerregelige tekst en vermenging van leading/trailing met left/right anchors. Xcode 15+ toont lay-outproblemen in de Runtime Issue Navigator en biedt automatische correcties. Gebruik voor complexe lay-outs Debug View Hierarchy: gele labels duiden op ambiguous lay-out, rode op unsatisfiable.
| Fout | Oorzaak | Oplossing |
|---|---|---|
| translatesAutoresizingMaskIntoConstraints = true | Auto Layout is niet geactiveerd voor view | Stel false in voor alle programmatische views |
| Unsatisfiable Layout | Conflict Required (1000) constraints | Verlaag prioriteit van één naar Default High (750) |
| Ambiguous Layout | Onvoldoende constraints voor x/y/w/h | Voeg ontbrekende constraint toe of controleer intrinsic size |
| Tekstafkapping in UILabel | Content Hugging Priority lager dan concurrent | Verhoog hugging priority naar 252+ |
| Vermenging LTR/RTL-anchors | leadingAnchor met rightAnchor | Gebruik alleen leading/trailing voor RTL-ondersteuning |
Veelgestelde vragen
Frame-based lay-out stelt vaste coördinaten x, y, width, height in voor elk element. Auto Layout gebruikt wiskundige beperkingen (constraints) — relaties tussen elementen: «label.leading = button.trailing + 8». Frame-based lay-out past zich niet aan aan de schermgrootte; Auto Layout herberekent automatisch posities bij rotatie, Split View of wijziging van Dynamic Type.
UIStackView is optimaal voor lineaire lay-outs: rijen, kolommen, formulieren, parameterlijsten. NSLayoutConstraint is nodig voor overlappende views, pixel-nauwkeurige positionering, aangepaste bounds-animatie en gevallen waarin de ruimteverdeling ongelijk is en niet wordt gedekt door de distribution van UIStackView. In de praktijk wordt 80% van de lay-outs opgelost met UIStackView, 20% met handmatige constraints.
Content Hugging Priority (weerstand tegen uitrekken) — de prioriteit die bepaalt hoeveel een element weerstand biedt aan het vergroten van zijn afmeting boven de Intrinsic Content Size. Standaardwaarde — 251. Als twee elementen concurreren om vrije ruimte, blijft het element met de hoogste hugging priority op zijn grootte en wordt de andere uitgerekt. Compression Resistance Priority (standaard 749) werkt analoog voor samendrukken.
Auto Layout past zich automatisch aan Dynamic Type aan als constraints gebruik maken van de intrinsic content size van labels. Bij vergroting van het lettertype wordt UILabel groter, waardoor aangrenzende elementen worden verschoven via constraints. UIStackView met distribution = fillProportionally herverdeelt de ruimte evenredig aan de nieuwe intrinsic sizes. Safe Area en Layout Margins houden ook rekening met toegankelijkheidsinstellingen.
Unsatisfiable Layout ontstaat wanneer twee Required (priority = 1000) constraints elkaar tegenspreken: bijvoorbeeld view.leading = superview.leading + 16 en view.trailing = superview.leading + 200 bij een superview van 100pt breed. Het Cassowary-algoritme kan geen oplossing vinden en de app crasht met NSConstraintException. Oplossing — verlaag de prioriteit van een van de conflicterende constraints naar Default High (750).
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook