Auto Layout: ce este, layout adaptiv al interfețelor iOS

Autor: IT Sectr Publicat: 2026-02-21 Timp de citire: 9 min

Auto Layout — sistem de poziționare adaptivă a elementelor de interfață de la Apple, bazat pe constrângeri matematice (constraints). Dezvoltat pentru iOS 6 (2012), Auto Layout permite crearea de interfețe care se afișează corect pe toate dispozitivele — de la iPhone SE (4.7″) la iPad Pro (12.9″) și Dynamic Island. Conform Apple WWDC Session 202 (2024), peste 90% din aplicațiile din App Store folosesc Auto Layout sau alternativa sa declarativă — SwiftUI layout system. Constraints descriu dependențele între elementele UI prin ecuații liniare: view1.leading = view2.trailing + 8.

Principalul

  • Auto Layout — sistem de layout adaptiv Apple prin constrângeri matematice (constraints) pentru toate dimensiunile de ecrane.
  • Constraints — ecuații liniare de forma view1.attribute = multiplier × view2.attribute + constant, rezolvate prin algoritmul Cassowary.
  • UIStackView — container care gestionează automat constraints pentru view-urile imbricate (horizontal/vertical, alignment, distribution).
  • NSLayoutConstraint — API programatic pentru crearea de constrângeri în cod cu activare prin isActive = true.
  • Safe Area și Layout Margins — margini încorporate Auto Layout care exclud intersectarea cu Dynamic Island, Notch și Home Indicator.

Ce este Auto Layout?

Auto Layout — este sistemul de layout adaptiv Apple, care utilizează constrângeri matematice (constraints) pentru poziționarea elementelor UI. Spre deosebire de layout-ul pe bază de cadre (frame-based layout), unde fiecare element are coordonate fixe x, y, width, height, Auto Layout descrie relațiile între elemente: «butonul se află la 8pt de marginea dreaptă a părintelui» sau «lățimea câmpului text este egală cu jumătate din lățimea ecranului». Mecanismul se bazează pe algoritmul Cassowary, dezvoltat la University of Washington (Greg J. Badros, 1999) și implementat de Apple în iOS 6. Cassowary rezolvă un sistem de inegalități liniare cu priorități — Required (1000), Default High (750), Default Low (250) — ceea ce permite gestionarea conflictelor de constrângeri. Auto Layout suportă trei tipuri de dimensiuni: intrinsic (dimensiunea naturală a elementului determinată de conținut), explicit (constraint specificat explicit) și compressible/stretchable (mod elastic prin Content Hugging Priority și Compression Resistance Priority).

Intrinsic Content Size și Priorități

Fiecare element UI în Auto Layout are Intrinsic Content Size — dimensiunea naturală determinată de conținutul său. Pentru UILabel depinde de text și font, pentru UIImageView — de dimensiunile imaginii. Content Hugging Priority (rezistența la întindere) și Compression Resistance Priority (rezistența la comprimare) gestionează comportamentul elementului la modificarea spațiului disponibil. Valorile standard: 251 pentru hugging și 749 pentru compression resistance. Dacă două elemente concurează pentru spațiu, prioritatea determină care se va întinde primul. Înțelegerea acestor priorități este cheia eliminării Ambiguous Layout (layout ambiguu), pe care Xcode îl evidențiază în debugger.

Anatomia unui Constraint

Constraint este descris printr-o ecuație: view1.attribute = multiplier × view2.attribute + constant. Atributele includ leading, trailing, top, bottom, centerX, centerY, width, height, firstBaseline, lastBaseline. Multiplier este folosit pentru relații proporționale (lățime view1 = 0.5 × lățime superview). Constant definește un spațiu fix (leading = superview.leading + 16). Instrumentele Interface Builder permit specificarea vizuală a constraints prin tragere cu Ctrl, dar layout-urile complexe necesită creare programatică prin NSLayoutConstraint sau VFL (Visual Format Language), pe care Apple recomandă să-l înlocuiți cu NSLayoutConstraint din iOS 9.

Cum funcționează Constraints în iOS

Sistemul de constraints este rezolvat ca o problemă de programare liniară: algoritmul Cassowary găsește poziționarea optimă a tuturor elementelor, satisfăcând toate constrângerile cu prioritățile lor. Dacă constraints se contrazic reciproc, apare Unsatisfiable Layout — o excepție pe care Xcode o înregistrează cu o descriere detaliată a conflictului. Dacă constraints nu sunt suficiente pentru a determina poziția a cel puțin unui element, apare Ambiguous Layout — elementele se afișează într-o poziție arbitrară. Apple recomandă un set minim: pentru fiecare element trebuie specificate position (x, y) și size (width, height) — explicit sau prin intrinsic content size. Constraints pot fi first-class: elementul principal (de exemplu, superview) și cel dependent (view copil) creează o ierarhie.

Algoritmul Cassowary și prioritățile

Cassowary folosește metoda Sequential Quadratic Programming pentru a rezolva sisteme de inegalități liniare. Fiecare constraint are o prioritate de la 1 la 1000. Required (1000) — constrângere obligatorie; dacă nu poate fi îndeplinită, aplicația crapă cu NSConstraintException. Default High (750) — recomandată; Default Low (250) — cea mai puțin importantă. La conflict, Cassowary relaxează constrângerile cu prioritate mai mică. De exemplu, dacă două elemente necesită lățime fixă, iar ecranul este prea îngust, constraint-ul cu prioritate mai mică este relaxat. În Xcode Debug View Hierarchy (instrument de debug disponibil din Xcode 6) evidențiază doar problemele cu Required constraints — restul sunt procesate fără eroare.

UIStackView: gestionarea automată a Constraints

UIStackView — container introdus în iOS 9 (2015), care creează și gestionează automat constraints pentru arrangedSubviews imbricate. UIStackView suportă două axe: horizontal (aranjare orizontală) și vertical (verticală). Setările distribution determină distribuirea spațiului: fill (umplere proporțională cu hugging priority), fillEqually (dimensiuni egale), fillProportionally (proporțional cu intrinsic content size), equalSpacing (spații egale), equalCentering (distanțe egale între centre). Alignment specifică alinierea transversală pe axă: fill, leading, center, trailing (pentru horizontal) sau fill, top, center, bottom (pentru vertical). UIStackView gestionează automat spacing, baseline alignment și adaptarea la 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 = "Ghid Auto Layout"
        label.font = UIFont.preferredFont(forTextStyle: .headline)
        
        let button = UIButton(type: .system)
        button.setTitle("Aplică", 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)
        ])
    }
}

Codul creează un UIStackView vertical cu două elemente (UILabel și UIButton), distribuite uniform (fillEqually) cu un spațiu de 8pt. Stack este centrat pe ecran cu margini de cel puțin 16pt. translatesAutoresizingMaskIntoConstraints = false este obligatoriu la crearea programatică a constraints — fără el Auto Layout nu funcționează. În IT Sectr, UIStackView este folosit în 80% din ecranele proiectelor iOS pentru construirea de formulare adaptive, liste de setări și carduri.

Stack View-uri imbricate

UIStackView-urile pot fi imbricate: stack orizontal în interiorul unuia vertical — un model standard pentru layout-uri complexe. Stack-ul extern gestionează rândurile, cel intern — coloanele din interiorul rândului. Combinația de axis, alignment și distribution la fiecare nivel oferă o flexibilitate practic nelimitată fără niciun constraint manual. Apple recomandă utilizarea UIStackView ca instrument principal de layout în UIKit, apelând la NSLayoutConstraint manual doar pentru cazuri neacoperite de stack: view-uri suprapuse, poziționare precisă la pixel, animație personalizată bounds.

NSLayoutConstraint: crearea programatică a constrângerilor

NSLayoutConstraint — API programatic pentru crearea de constrângeri individuale în cod. Fiecare constraint este creat prin inițializator cu parametri: item, attribute, relatedBy, toItem, attribute, multiplier, constant. Din iOS 9 Apple a introdus Anchor API — o sintaxă mai lizibilă prin proprietățile view.leadingAnchor, view.trailingAnchor, view.topAnchor, view.bottomAnchor, view.centerXAnchor, view.centerYAnchor, view.widthAnchor, view.heightAnchor. Anchor API setează automat relatedBy = .equal și folosește First Item/Second Item din Anchor, reducând codul cu 40% comparativ cu NSLayoutConstraint clasic.

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)
        ])
    }
}

Codul poziționează childView cu margini de la safeAreaLayoutGuide (top) și marginile ecranului (leading/trailing). lessThanOrEqualTo pentru bottom garantează că view nu va depăși limita inferioară. Anchor API aruncă o excepție în faza de compilare dacă anchor-urile sunt incompatibile (de exemplu, leadingAnchor se amestecă cu rightAnchor), prevenind erorile de runtime. Apple recomandă Anchor API ca standard pentru Auto Layout programatic începând cu iOS 9.

Safe Area și Layout Margins în Auto Layout

Safe Area — zona ecranului neacoperită de elementele sistemului: Dynamic Island, Notch, Status Bar, Home Indicator, colțuri rotunjite. În iOS 11 Apple a înlocuit topLayoutGuide/bottomLayoutGuide cu safeAreaLayoutGuide, care se adaptează automat la orientarea dispozitivului și prezența decupajului ecranului. Layout Margins — marginile interne implicite ale view (16pt pe iOS, 20pt pe iPadOS). Pentru UILayoutGuide se pot seta directionalLayoutMargins personalizate ținând cont de localizarea RIGHT-TO-LEFT. Auto Layout ia automat în considerare safe area la utilizarea safeAreaLayoutGuide în anchor-uri.

Adaptarea la Dynamic Island și Notch

Pe dispozitivele cu Dynamic Island (iPhone 14 Pro și mai noi) și Notch (iPhone X–13) Safe Area exclude 44pt de sus în portret (59pt cu Dynamic Island în stare activă). Home Indicator adaugă 34pt de jos. Pentru adaptare corectă, toate top-constraints trebuie legate de safeAreaLayoutGuide.topAnchor, nu de view.topAnchor. Bottom-constraints — de safeAreaLayoutGuide.bottomAnchor sau view.bottomAnchor cu rezervă pentru Home Indicator. În IT Sectr testăm toate ecranele pe simulatoarele iPhone SE (2022), iPhone 14 Pro Max și iPad Pro 12.9″ — trei dispozitive care acoperă toate variantele de safe area.

Erori tipice Auto Layout

Cele mai frecvente erori la lucrul cu Auto Layout: translatesAutoresizingMaskIntoConstraints = false uitat, conflict Required constraints (prioritate 1000), Ambiguous Layout (constraints insuficiente pentru determinarea poziției), Content Hugging Priority incorect pentru UILabel cu text multiline și amestecarea leading/trailing cu left/right anchors. Xcode 15+ afișează problemele de layout în Runtime Issue Navigator și oferă corecții automate. Pentru layout-uri complexe folosiți Debug View Hierarchy: etichetele galbene indică ambiguous layout, cele roșii — unsatisfiable.

EroareCauzăSoluție
translatesAutoresizingMaskIntoConstraints = trueAuto Layout nu este activat pentru viewSetați false pentru toate view-urile programatice
Unsatisfiable LayoutConflict Required (1000) constraintsReduceți prioritatea unuia la Default High (750)
Ambiguous LayoutConstraints insuficiente pentru x/y/w/hAdăugați constraint lipsă sau verificați intrinsic size
Trunchiere text în UILabelContent Hugging Priority mai mic decât concurentulCreșteți hugging priority la 252+
Amestecare anchor-uri LTR/RTLleadingAnchor cu rightAnchorFolosiți doar leading/trailing pentru suport RTL

Întrebări frecvente

Cu ce diferă Auto Layout de layout-ul pe bază de cadre?

Layout-ul pe bază de cadre stabilește coordonate fixe x, y, width, height pentru fiecare element. Auto Layout folosește constrângeri matematice (constraints) — relații între elemente: «label.leading = button.trailing + 8». Layout-ul pe bază de cadre nu se adaptează la dimensiunea ecranului; Auto Layout recalculează automat pozițiile la rotire, Split View sau modificarea Dynamic Type.

Când ar trebui să folosesc UIStackView în loc de NSLayoutConstraint?

UIStackView este optim pentru layout-uri liniare: rânduri, coloane, formulare, liste de parametri. NSLayoutConstraint este necesar pentru view-uri suprapuse, poziționare precisă la pixeli, animație personalizată bounds și cazuri când distribuția spațiului este neuniformă și nu este acoperită de distribution UIStackView. În practică, 80% din layout-uri se rezolvă cu UIStackView, 20% — cu constraints manuale.

Ce este Content Hugging Priority în Auto Layout?

Content Hugging Priority (rezistența la întindere) — prioritatea care determină cât de mult un element rezistă la creșterea dimensiunii sale peste Intrinsic Content Size. Valoarea implicită — 251. Dacă două elemente concurează pentru spațiu liber, elementul cu hugging priority mai mare rămâne la dimensiunea sa, iar al doilea se întinde. Compression Resistance Priority (implicit 749) funcționează similar pentru comprimare.

Cum funcționează Auto Layout cu Dynamic Type?

Auto Layout se adaptează automat la Dynamic Type dacă constraints folosesc intrinsic content size al etichetelor. La creșterea dimensiunii fontului, UILabel se extinde, deplasând elementele învecinate prin constraints. UIStackView cu distribution = fillProportionally redistribuie spațiul proporțional cu noile intrinsic size. Safe Area și Layout Margins iau în considerare și setările de accesibilitate.

De ce apare Unsatisfiable Layout?

Unsatisfiable Layout apare când două Required (priority = 1000) constraints se contrazic reciproc: de exemplu, view.leading = superview.leading + 16 și view.trailing = superview.leading + 200 la un superview de 100pt lățime. Algoritmul Cassowary nu poate găsi o soluție, iar aplicația crapă cu NSConstraintException. Soluția — reduceți prioritatea unuia dintre constraints-urile conflictuale la Default High (750).

Concluzii

  • Auto Layout — sistem de layout adaptiv Apple bazat pe algoritmul Cassowary, care rezolvă un sistem de constrângeri liniare cu priorități.
  • Constraints — ecuații de forma view1.attribute = multiplier × view2.attribute + constant cu priorități de la 1 la 1000 (Required).
  • UIStackView — container care gestionează automat constraints pentru arrangedSubviews cu suport pentru axe, distribution și alignment.
  • NSLayoutConstraint cu Anchor API — standard programatic din iOS 9, reducând codul cu 40% față de API-ul clasic.
  • Safe Area — zonă fără Dynamic Island, Notch, Home Indicator; obligatorie pentru legarea top/bottom constraints.
  • Erori tipice — translatesAutoresizingMaskIntoConstraints uitat, conflict Required, Ambiguous Layout, amestecare anchor-uri LTR/RTL.
  • Intrinsic Content Size și prioritățile (hugging 251, compression 749) gestionează comportamentul elementelor la modificarea spațiului disponibil.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și