Auto Layout — az Apple adaptív felületi elem pozicionáló rendszere, matematikai korlátozásokon (constraints) alapul. Az iOS 6-hoz (2012) kifejlesztett Auto Layout lehetővé teszi olyan felületek létrehozását, amelyek minden eszközön helyesen jelennek meg — az iPhone SE-től (4.7″) az iPad Pro-ig (12.9″) és a Dynamic Island-ig. Az Apple WWDC Session 202 (2024) szerint az App Store-ban lévő alkalmazások több mint 90%-a használja az Auto Layout-ot vagy annak deklaratív alternatíváját — a SwiftUI layout system-et. A Constraints lineáris egyenleteken keresztül írja le az UI-elemek közötti függőségeket: view1.leading = view2.trailing + 8.
Főbb pontok
Auto Layout — az Apple adaptív elrendezési rendszere, amely matematikai korlátozásokat (constraints) használ az UI-elemek pozicionálásához. A keret-alapú elrendezéstől (frame-based layout) eltérően, ahol minden elem fix x, y, width, height koordinátákkal rendelkezik, az Auto Layout az elemek közötti kapcsolatokat írja le: «a gomb 8pt-re van a szülő jobb szélétől» vagy «a szövegmező szélessége egyenlő a képernyőszélesség felével». A mechanizmus a Washingtoni Egyetemen (Greg J. Badros, 1999) kifejlesztett és az Apple által az iOS 6-ban bevezetett Cassowary-algoritmuson alapul. A Cassowary prioritásokkal rendelkező lineáris egyenlőtlenség-rendszereket old meg — Required (1000), Default High (750), Default Low (250) — ami lehetővé teszi a korlátozási konfliktusok kezelését. Az Auto Layout három mérettípust támogat: intrinsic (az elem természetes mérete a tartalom által meghatározva), explicit (kifejezetten megadott constraint) és compressible/stretchable (rugalmas mód a Content Hugging Priority és Compression Resistance Priority segítségével).
Minden UI-elem az Auto Layout-ban rendelkezik Intrinsic Content Size-szal — a tartalma által meghatározott természetes mérettel. UILabel esetében ez a szövegtől és betűtípustól, UIImageView esetében a kép méreteitől függ. A Content Hugging Priority (nyújtással szembeni ellenállás) és a Compression Resistance Priority (összenyomással szembeni ellenállás) kezeli az elem viselkedését a rendelkezésre álló hely változásakor. Alapértékek: 251 a hugging és 749 a compression resistance esetében. Ha két elem helyért versenyez, a prioritás határozza meg, melyik nyúlik meg először. E prioritások megértése a kulcs az Ambiguous Layout (kétértelmű elrendezés) megszüntetéséhez, amelyet az Xcode a debuggerben kiemel.
A constraint egy egyenlettel írható le: view1.attribute = multiplier × view2.attribute + constant. Az attribútumok közé tartozik a leading, trailing, top, bottom, centerX, centerY, width, height, firstBaseline, lastBaseline. A multiplier arányos kapcsolatokhoz használatos (view1 szélessége = 0.5 × superview szélessége). A constant fix távolságot határoz meg (leading = superview.leading + 16). Az Interface Builder eszközei lehetővé teszik a constraints vizuális beállítását Ctrl-húzással, de az összetett elrendezések programozott létrehozást igényelnek NSLayoutConstraint vagy VFL (Visual Format Language) segítségével, amelyet az Apple az iOS 9-től kezdve NSLayoutConstraint-re javasol cserélni.
A constraints rendszer lineáris programozási feladatként oldódik meg: a Cassowary-algoritmus megtalálja az összes elem optimális elhelyezését, kielégítve az összes korlátozást a prioritások figyelembevételével. Ha a constraints ellentmond egymásnak, Unsatisfiable Layout keletkezik — egy kivétel, amelyet az Xcode naplóz a konfliktus részletes leírásával. Ha a constraints nem elegendő legalább egy elem pozíciójának meghatározásához, Ambiguous Layout keletkezik — az elemek tetszőleges helyen jelennek meg. Az Apple minimális készletet javasol: minden elemhez meg kell adni a position (x, y) és size (width, height) értékeket — kifejezetten vagy intrinsic content size segítségével. A constraints lehet first-class: a vezető elem (pl. superview) és a függő (gyermek view) hierarchiát hoz létre.
A Cassowary a Sequential Quadratic Programming módszert használja lineáris egyenlőtlenség-rendszerek megoldására. Minden constraint prioritása 1-től 1000-ig terjed. Required (1000) — kötelező korlátozás; ha nem teljesíthető, az alkalmazás NSConstraintException-nel összeomlik. Default High (750) — ajánlott; Default Low (250) — a legkevésbé fontos. Konfliktus esetén a Cassowary lazítja az alacsonyabb prioritású korlátozásokat. Például, ha két elem fix szélességet igényel, de a képernyő túl keskeny, az alacsonyabb prioritású constraint lazul. Az Xcode Debug View Hierarchy (Xcode 6-tól elérhető hibakereső eszköz) csak a Required constraints problémáit emeli ki — a többiek hiba nélkül kerülnek feldolgozásra.
UIStackView — egy iOS 9-ben (2015) bevezetett tároló, amely automatikusan létrehozza és kezeli a constraints-eket a beágyazott arrangedSubviews számára. Az UIStackView két tengelyt támogat: horizontal (vízszintes elrendezés) és vertical (függőleges). A distribution beállításai határozzák meg a hely elosztását: fill (kitöltés a hugging priority arányában), fillEqually (egyenlő méretek), fillProportionally (arányosan az intrinsic content size-hoz), equalSpacing (egyenlő távolságok), equalCentering (egyenlő távolság a középpontok között). Az alignment a tengelyre merőleges igazítást határozza meg: fill, leading, center, trailing (horizontal esetén) vagy fill, top, center, bottom (vertical esetén). Az UIStackView automatikusan kezeli a spacing, baseline alignment és a Dynamic Type-hoz való alkalmazkodást.
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 útmutató"
label.font = UIFont.preferredFont(forTextStyle: .headline)
let button = UIButton(type: .system)
button.setTitle("Alkalmaz", 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)
])
}
}A kód létrehoz egy függőleges UIStackView-t két elemmel (UILabel és UIButton), egyenletesen elosztva (fillEqually) 8pt távolsággal. A stack a képernyő közepére van igazítva, legalább 16pt margóval a szélektől. A translatesAutoresizingMaskIntoConstraints = false kötelező a constraints programozott létrehozásakor — enélkül az Auto Layout nem működik. Az IT Sectr-nél az UIStackView az iOS projektek 80%-ában használatos adaptív űrlapok, beállításlisták és kártyák építéséhez.
Az UIStackView-k beágyazhatók: vízszintes stack a függőlegesen belül — szabványos minta összetett elrendezésekhez. A külső stack a sorokat kezeli, a belső — a soron belüli oszlopokat. Az axis, alignment és distribution kombinációja minden szinten gyakorlatilag korlátlan rugalmasságot biztosít egyetlen kézi constraint nélkül is. Az Apple az UIStackView használatát javasolja elsődleges elrendezési eszközként az UIKit-ben, kézi NSLayoutConstraint-hez csak a stack által nem lefedett esetekben folyamodva: átfedő view-k, pixel-pontos pozicionálás, egyéni bounds animáció.
NSLayoutConstraint — programozói API egyedi korlátozások létrehozásához kódban. Minden constraint egy inicializátoron keresztül jön létre paraméterekkel: item, attribute, relatedBy, toItem, attribute, multiplier, constant. Az iOS 9-től az Apple bevezette az Anchor API-t — egy olvashatóbb szintaxist a view.leadingAnchor, view.trailingAnchor, view.topAnchor, view.bottomAnchor, view.centerXAnchor, view.centerYAnchor, view.widthAnchor, view.heightAnchor tulajdonságokon keresztül. Az Anchor API automatikusan beállítja a relatedBy = .equal értéket, és a First Item/Second Item használja az Anchor-ból, 40%-kal csökkentve a kódot a klasszikus NSLayoutConstraint-hez képest.
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)
])
}
}A kód a childView-t pozicionálja margókkal a safeAreaLayoutGuide-tól (top) és a képernyő széleitől (leading/trailing). A lessThanOrEqualTo a bottom esetében garantálja, hogy a view nem lépi át az alsó határt. Az Anchor API kivételt dob a fordítási fázisban, ha az anchor-ok nem kompatibilisek (pl. a leadingAnchor keveredik a rightAnchor-ral), megelőzve a futásidejű hibákat. Az Apple az Anchor API-t ajánlja szabványként a programozott Auto Layout-hoz iOS 9-től kezdve.
Safe Area — a képernyő azon területe, amelyet nem takarnak rendszerelemek: Dynamic Island, Notch, Status Bar, Home Indicator, lekerekített sarkok. Az iOS 11-ben az Apple lecserélte a topLayoutGuide/bottomLayoutGuide-ot a safeAreaLayoutGuide-ra, amely automatikusan alkalmazkodik az eszköz tájolásához és a képernyő kivágás meglétéhez. Layout Margins — a view alapértelmezett belső margói (16pt iOS-en, 20pt iPadOS-en). Az UILayoutGuide-hoz egyéni directionalLayoutMargins állítható be a RIGHT-TO-LEFT lokalizáció figyelembevételével. Az Auto Layout automatikusan figyelembe veszi a safe area-t a safeAreaLayoutGuide használatakor az anchor-okban.
A Dynamic Island (iPhone 14 Pro és újabb) és Notch (iPhone X–13) eszközökön a Safe Area 44pt-t zár ki felülről portré módban (59pt aktív Dynamic Island esetén). A Home Indicator 34pt-t ad hozzá alulról. A helyes alkalmazkodáshoz minden top-constraint-et a safeAreaLayoutGuide.topAnchor-hoz kell kötni, nem a view.topAnchor-hoz. Bottom-constraint-ek — a safeAreaLayoutGuide.bottomAnchor-hoz vagy a view.bottomAnchor-hoz a Home Indicator tartalékával. Az IT Sectr-nél minden képernyőt iPhone SE (2022), iPhone 14 Pro Max és iPad Pro 12.9″ szimulátorokon tesztelünk — három eszköz, amely lefedi a safe area összes változatát.
A leggyakoribb hibák az Auto Layout használatakor: elfelejtett translatesAutoresizingMaskIntoConstraints = false, ütköző Required constraints (prioritás 1000), Ambiguous Layout (nem elegendő constraints a pozíció meghatározásához), helytelen Content Hugging Priority a többsoros szövegű UILabel-nél és a leading/trailing összekeverése a left/right anchor-okkal. Az Xcode 15+ megjeleníti az elrendezési problémákat a Runtime Issue Navigator-ban, és automatikus javításokat kínál. Összetett elrendezésekhez használja a Debug View Hierarchy-t: a sárga címkék ambiguous layout-ot, a pirosak unsatisfiable-t jeleznek.
| Hiba | Ok | Megoldás |
|---|---|---|
| translatesAutoresizingMaskIntoConstraints = true | Auto Layout nincs aktiválva a view-hoz | Állítsa false-ra az összes programozott view-nál |
| Unsatisfiable Layout | Required (1000) constraints ütközés | Csökkentse az egyik prioritását Default High (750) értékre |
| Ambiguous Layout | Nem elegendő constraints x/y/w/h-hoz | Adjon hozzá hiányzó constraint-et vagy ellenőrizze az intrinsic size-ot |
| Szöveg csonkolása UILabel-ben | Content Hugging Priority alacsonyabb a versenytársnál | Növelje a hugging priority-t 252+-ra |
| LTR/RTL anchor-ok keverése | leadingAnchor a rightAnchor-ral | Csak leading/trailing használata az RTL támogatáshoz |
Gyakran ismételt kérdések
Keret-alapú elrendezés fix x, y, width, height koordinátákat rendel minden elemhez. Az Auto Layout matematikai korlátozásokat (constraints) használ — kapcsolatokat az elemek között: «label.leading = button.trailing + 8». A keret-alapú elrendezés nem alkalmazkodik a képernyő méretéhez; az Auto Layout automatikusan újraszámolja a pozíciókat forgatáskor, Split View-nál vagy Dynamic Type változáskor.
UIStackView optimális lineáris elrendezésekhez: sorok, oszlopok, űrlapok, paraméterlisták. NSLayoutConstraint szükséges átfedő view-khoz, pixel-pontos pozicionáláshoz, egyéni bounds animációhoz és olyan esetekben, ahol a hely eloszlása egyenetlen és nem fedi le az UIStackView distribution. A gyakorlatban az elrendezések 80%-a UIStackView-vel, 20%-a kézi constraints-ekkel oldható meg.
Content Hugging Priority (nyújtással szembeni ellenállás) — prioritás, amely meghatározza, mennyire ellenáll az elem a méretének Intrinsic Content Size fölé növelésének. Alapérték — 251. Ha két elem versenyez a szabad helyért, a magasabb hugging priority-val rendelkező elem megőrzi méretét, a másik megnyúlik. A Compression Resistance Priority (alapértelmezett 749) hasonlóan működik az összenyomás esetében.
Az Auto Layout automatikusan alkalmazkodik a Dynamic Type-hoz, ha a constraints a címkék intrinsic content size-át használja. A betűméret növekedésekor az UILabel kitágul, elmozdítva a szomszédos elemeket a constraints-eken keresztül. Az UIStackView distribution = fillProportionally beállítással arányosan osztja újra a helyet az új intrinsic size-ok szerint. A Safe Area és Layout Margins szintén figyelembe veszik az akadálymentességi beállításokat.
Unsatisfiable Layout akkor keletkezik, amikor két Required (priority = 1000) constraints ellentmond egymásnak: például view.leading = superview.leading + 16 és view.trailing = superview.leading + 200 egy 100pt szélességű superview esetén. A Cassowary-algoritmus nem talál megoldást, és az alkalmazás NSConstraintException-nel összeomlik. Megoldás — csökkentse az egyik ütköző constraint prioritását Default High (750) értékre.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is