Auto Layout é o sistema de posicionamento adaptativo de elementos de interface da Apple, baseado em restrições matemáticas (constraints). Desenvolvido para iOS 6 (2012), o Auto Layout permite criar interfaces que são exibidas corretamente em todos os dispositivos — desde iPhone SE (4.7″) até iPad Pro (12.9″) e Dynamic Island. De acordo com a Apple WWDC Session 202 (2024), mais de 90% dos aplicativos na App Store usam Auto Layout ou sua alternativa declarativa — SwiftUI layout system. Os Constraints descrevem dependências entre elementos de UI através de equações lineares: view1.leading = view2.trailing + 8.
Pontos principais
Auto Layout é o sistema de layout adaptável da Apple que utiliza restrições matemáticas (constraints) para posicionar elementos de UI. Ao contrário do layout baseado em frames (frame-based layout), onde cada elemento tem coordenadas fixas x, y, width, height, o Auto Layout descreve relações entre elementos: «o botão está a 8pt da borda direita do pai» ou «a largura do campo de texto é igual à metade da largura da tela». O mecanismo é baseado no algoritmo Cassowary, desenvolvido na University of Washington (Greg J. Badros, 1999) e implementado pela Apple no iOS 6. Cassowary resolve um sistema de desigualdades lineares com prioridades — Required (1000), Default High (750), Default Low (250) — permitindo gerenciar conflitos de restrições. Auto Layout suporta três tipos de tamanho: intrinsic (tamanho natural do elemento determinado pelo conteúdo), explicit (restrição definida explicitamente) e compressible/stretchable (modo elástico através de Content Hugging Priority e Compression Resistance Priority).
Cada elemento de UI no Auto Layout tem um Intrinsic Content Size — um tamanho natural determinado pelo seu conteúdo. Para UILabel isso depende do texto e da fonte, para UIImageView — das dimensões da imagem. Content Hugging Priority (resistência ao esticamento) e Compression Resistance Priority (resistência à compressão) controlam o comportamento do elemento quando o espaço disponível muda. Valores padrão: 251 para hugging e 749 para compression resistance. Se dois elementos competem por espaço, a prioridade determina qual deles se estica primeiro. Compreender essas prioridades é a chave para resolver Ambiguous Layout (layout ambíguo), que o Xcode destaca no depurador.
Um constraint é descrito pela equação: view1.attribute = multiplier × view2.attribute + constant. Os atributos incluem leading, trailing, top, bottom, centerX, centerY, width, height, firstBaseline, lastBaseline. Multiplier é usado para relações proporcionais (largura da view1 = 0.5 × largura da superview). Constant define um deslocamento fixo (leading = superview.leading + 16). As ferramentas do Interface Builder permitem criar constraints visualmente através de Ctrl-arrasto, mas layouts complexos exigem criação programática através de NSLayoutConstraint ou VFL (Visual Format Language), que a Apple recomenda substituir por NSLayoutConstraint desde o iOS 9.
O sistema de constraints é resolvido como um problema de programação linear: o algoritmo Cassowary encontra a disposição ideal de todos os elementos que satisfaz todas as restrições considerando suas prioridades. Se os constraints se contradizem, ocorre um Unsatisfiable Layout — uma exceção que o Xcode registra com uma descrição detalhada do conflito. Se não há constraints suficientes para determinar a posição de pelo menos um elemento, ocorre Ambiguous Layout — os elementos são exibidos em posições arbitrárias. A Apple recomenda um conjunto mínimo: para cada elemento, position (x, y) e size (width, height) devem ser definidos — explicitamente ou através de intrinsic content size. Os constraints podem ser de primeira classe: o elemento líder (por exemplo, superview) e o seguidor (view filha) criam uma hierarquia.
Cassowary utiliza o método Sequential Quadratic Programming para resolver sistemas de desigualdades lineares. Cada constraint tem uma prioridade de 1 a 1000. Required (1000) é uma restrição obrigatória; se não puder ser cumprida, o aplicativo falha com NSConstraintException. Default High (750) é recomendada; Default Low (250) é a menos importante. Durante um conflito, Cassowary relaxa as restrições de prioridade mais baixa. Por exemplo, se dois elementos exigem largura fixa mas a tela é muito estreita, o constraint de prioridade mais baixa é relaxado. No Xcode Debug View Hierarchy (ferramenta de depuração disponível desde o Xcode 6) destaca apenas problemas com constraints Required — os demais são tratados sem erro.
UIStackView é um contêiner apresentado no iOS 9 (2015) que cria e gerencia automaticamente constraints para arrangedSubviews aninhadas. UIStackView suporta dois eixos: horizontal e vertical. As configurações de distribution determinam a distribuição do espaço: fill (preenchimento proporcional conforme hugging priority), fillEqually (tamanhos iguais), fillProportionally (proporcional ao intrinsic content size), equalSpacing (espaçamento igual), equalCentering (distâncias iguais entre centros). Alignment define o alinhamento transversal: fill, leading, center, trailing (para horizontal) ou fill, top, center, bottom (para vertical). UIStackView gerencia automaticamente espaçamento, alinhamento de linha base e adaptação ao 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 Guide"
label.font = UIFont.preferredFont(forTextStyle: .headline)
let button = UIButton(type: .system)
button.setTitle("Apply", 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)
])
}
}O código cria um UIStackView vertical com dois elementos (UILabel e UIButton), distribuídos uniformemente (fillEqually) com espaçamento de 8pt. A stack é centralizada na tela com margens de pelo menos 16pt das bordas. translatesAutoresizingMaskIntoConstraints = false é obrigatório ao criar constraints programaticamente — sem ele, o Auto Layout não funciona. Na IT Sectr, UIStackView é usado em 80% das telas de projetos iOS para construir formulários adaptativos, listas de configurações e cartões.
UIStackViews podem ser aninhados: uma stack horizontal dentro de uma vertical é um padrão padrão para layouts complexos. A stack externa gerencia linhas, a interna gerencia colunas dentro de cada linha. A combinação de axis, alignment e distribution em cada nível fornece flexibilidade praticamente ilimitada sem um único constraint manual. A Apple recomenda UIStackView como a ferramenta de layout principal no UIKit, recorrendo a NSLayoutConstraint manual apenas para casos não cobertos por stacks: views sobrepostas, posicionamento preciso de pixels, animação personalizada de bounds.
NSLayoutConstraint é uma API programática para criar restrições individuais em código. Cada constraint é criado através de um inicializador com parâmetros: item, attribute, relatedBy, toItem, attribute, multiplier, constant. Desde o iOS 9, a Apple apresentou a Anchor API — uma sintaxe mais legível através das propriedades view.leadingAnchor, view.trailingAnchor, view.topAnchor, view.bottomAnchor, view.centerXAnchor, view.centerYAnchor, view.widthAnchor, view.heightAnchor. A Anchor API define automaticamente relatedBy = .equal e usa First Item/Second Item dos Anchors, reduzindo o código em 40% em comparação com NSLayoutConstraint clássico.
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)
])
}
}O código posiciona childView com margens do safeAreaLayoutGuide (top) e das bordas da tela (leading/trailing). lessThanOrEqualTo para bottom garante que a view não ultrapasse o limite inferior. A Anchor API lança uma exceção em tempo de compilação se os anchors forem incompatíveis (por exemplo, leadingAnchor misturado com rightAnchor), prevenindo erros em tempo de execução. A Apple recomenda a Anchor API como padrão para Auto Layout programático desde o iOS 9.
Safe Area é a área da tela não coberta por elementos do sistema: Dynamic Island, Notch, Status Bar, Home Indicator, cantos arredondados. No iOS 11, a Apple substituiu topLayoutGuide/bottomLayoutGuide por safeAreaLayoutGuide, que se adapta automaticamente à orientação do dispositivo e à presença de recorte de tela. Layout Margins são margens internas padrão da view (16pt no iOS, 20pt no iPadOS). Para UILayoutGuide você pode definir directionalLayoutMargins personalizados considerando a localização RIGHT-TO-LEFT. Auto Layout respeita automaticamente a safe area ao usar safeAreaLayoutGuide nos anchors.
Em dispositivos com Dynamic Island (iPhone 14 Pro e posteriores) e Notch (iPhone X–13), a Safe Area exclui 44pt na parte superior em retrato (59pt com Dynamic Island em estado ativo). Home Indicator adiciona 34pt na parte inferior. Para adaptação correta, todas as constraints superiores devem ser vinculadas a safeAreaLayoutGuide.topAnchor, não a view.topAnchor. As constraints inferiores devem ser vinculadas a safeAreaLayoutGuide.bottomAnchor ou view.bottomAnchor com margem para Home Indicator. Na IT Sectr, testamos todas as telas nos simuladores iPhone SE (2022), iPhone 14 Pro Max e iPad Pro 12.9″ — três dispositivos que cobrem todas as variações de safe area.
Os erros mais frequentes ao trabalhar com Auto Layout: esquecer translatesAutoresizingMaskIntoConstraints = false, constraints Required em conflito (prioridade 1000), Ambiguous Layout (constraints insuficientes para determinar a posição), Content Hugging Priority incorreto para UILabel com texto multilinha e mistura de anchors leading/trailing com left/right. Xcode 15+ exibe problemas de layout no Runtime Issue Navigator e oferece correções automáticas. Para layouts complexos, use Debug View Hierarchy: marcadores amarelos indicam ambiguous layout, vermelhos indicam unsatisfiable.
| Erro | Causa | Solução |
|---|---|---|
| translatesAutoresizingMaskIntoConstraints = true | Auto Layout não ativado para a view | Definir false para todas as views programáticas |
| Unsatisfiable Layout | Conflito de constraints Required (1000) | Reduzir uma prioridade para Default High (750) |
| Ambiguous Layout | Constraints insuficientes para x/y/w/h | Adicionar constraint faltante ou verificar intrinsic size |
| Truncamento de texto em UILabel | Content Hugging Priority menor que o competidor | Aumentar hugging priority para 252+ |
| Mistura de anchors LTR/RTL | leadingAnchor com rightAnchor | Usar apenas leading/trailing para suporte RTL |
Perguntas frequentes
O layout baseado em frames define coordenadas fixas x, y, width, height para cada elemento. Auto Layout usa restrições matemáticas (constraints) — relações entre elementos: «label.leading = button.trailing + 8». O layout baseado em frames não se adapta ao tamanho da tela; Auto Layout recalcula automaticamente as posições ao girar, em Split View ou ao alterar Dynamic Type.
UIStackView é ideal para layouts lineares: linhas, colunas, formulários, listas de parâmetros. NSLayoutConstraint é necessário para views sobrepostas, posicionamento preciso de pixels, animação personalizada de bounds e casos onde a distribuição do espaço é desigual e não é coberta pela distribution do UIStackView. Na prática, 80% dos layouts são resolvidos com UIStackView, 20% com constraints manuais.
Content Hugging Priority (resistência ao esticamento) é uma prioridade que determina o quanto um elemento resiste ao aumento de seu tamanho além do Intrinsic Content Size. O valor padrão é 251. Se dois elementos competem por espaço livre, o elemento com maior hugging priority mantém seu tamanho enquanto o segundo se estica. Compression Resistance Priority (749 por padrão) funciona de forma similar para compressão.
Auto Layout se adapta automaticamente ao Dynamic Type se os constraints usarem o intrinsic content size dos rótulos. Ao aumentar o tamanho da fonte, UILabel se expande, deslocando elementos vizinhos através dos constraints. UIStackView com distribution = fillProportionally redistribui o espaço proporcionalmente aos novos intrinsic sizes. Safe Area e Layout Margins também respeitam as configurações de acessibilidade.
Unsatisfiable Layout ocorre quando dois constraints Required (priority = 1000) se contradizem: por exemplo, view.leading = superview.leading + 16 e view.trailing = superview.leading + 200 com uma superview de largura 100pt. O algoritmo Cassowary não encontra solução e o aplicativo falha com NSConstraintException. A solução é reduzir a prioridade de um dos constraints conflitantes para Default High (750).
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também