Noções Básicas do Protocolo Layout
Implemente sizeThatFits e placeSubviews.
Noções Básicas do Protocolo Layout é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.
Por que uma Disposição Personalizada?
O SwiftUI oferece HStack, VStack e ZStack, mas às vezes você precisa de uma lógica de disposição que elas não conseguem expressar — menus radiais, disposições em fluxo e grades assimétricas.
O protocolo Layout permite escrever essa lógica e ainda compor com visualizações SwiftUI comuns.
O Protocolo Layout
Layout exige dois métodos: sizeThatFits (qual é o meu tamanho?) e placeSubviews (onde cada filho deve ficar?).
Você torna um tipo de valor conforme ao protocolo e o usa como qualquer pilha integrada.
struct MyLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize { .zero }
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) { }
}Usando uma Disposição Personalizada
Um valor de Layout atua como um contêiner. Você passa as visualizações filhas em sua função de fechamento final, exatamente como em uma pilha.
var body: some View {
MyLayout {
Text("One")
Text("Two")
Text("Three")
}
}ProposedViewSize
O pai propõe um tamanho à sua disposição por meio de ProposedViewSize. Seus valores de width e height são opcionais: nil significa "não especificado; escolha seu tamanho ideal".
Os valores especiais .zero, .infinity e .unspecified consultam os tamanhos mínimo, máximo e ideal.
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
let width = proposal.width ?? 0
return CGSize(width: width, height: 44)
}sizeThatFits em Detalhes
sizeThatFits retorna o tamanho desejado pela sua disposição para uma determinada proposta. O SwiftUI pode chamá-lo várias vezes com propostas diferentes para entender sua flexibilidade.
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
// Sum child ideal sizes for a simple horizontal stack
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
let w = sizes.reduce(0) { $0 + $1.width }
let h = sizes.map(\.height).max() ?? 0
return CGSize(width: w, height: h)
}A Coleção de Subvisualizações
Subviews é uma coleção de representantes de cada filho. Cada representante responde a sizeThatFits e expõe prioridades de disposição e valores personalizados.
Você nunca vê as visualizações reais — apenas esses representantes de medição.
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
print(size)
}placeSubviews
placeSubviews atribui a cada filho uma posição dentro do retângulo bounds fornecido.
Chame place(at:anchor:proposal:) em cada representante de subvisualização.
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) {
var x = bounds.minX
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
subview.place(at: CGPoint(x: x, y: bounds.midY),
anchor: .leading,
proposal: .unspecified)
x += size.width
}
}Âncoras ao Posicionar
O parâmetro anchor indica qual ponto do filho ficará sobre a posição fornecida. .topLeading posiciona pelo canto superior esquerdo; .center centraliza o filho sobre o ponto.
subview.place(at: CGPoint(x: 0, y: 0),
anchor: .topLeading,
proposal: .unspecified)bounds Nem Sempre Começa na Origem
O retângulo bounds pode não começar em (0,0). Sempre posicione em relação a bounds.minX e bounds.minY, nunca em relação ao zero absoluto.
let startX = bounds.minX // not 0
let startY = bounds.minYUma Disposição Mínima com Espaçamento Uniforme
Juntando tudo, esta é uma disposição que organiza os filhos da esquerda para a direita, sem espaçamento. Os dois métodos permanecem consistentes: o tamanho informado corresponde ao posicionamento.
struct SimpleHStack: Layout {
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
return CGSize(width: sizes.reduce(0){ $0 + $1.width },
height: sizes.map(\.height).max() ?? 0)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
var x = bounds.minX
for s in subviews {
let size = s.sizeThatFits(.unspecified)
s.place(at: CGPoint(x: x, y: bounds.minY), anchor: .topLeading, proposal: .unspecified)
x += size.width
}
}
}A Consistência é Sua Responsabilidade
O SwiftUI confia que seus dois métodos estejam de acordo. Se placeSubviews usar mais espaço do que o informado por sizeThatFits, os filhos poderão ser cortados ou se sobrepor.
Mantenha os cálculos geométricos compartilhados entre os dois métodos.
Verificação Rápida: Fundamentos de Layout
Teste sua compreensão do protocolo Layout.
Recapitulação: Fundamentos do Protocolo Layout
O protocolo Layout transforma a lógica de disposição personalizada em um contêiner reutilizável. sizeThatFits informa seu tamanho para um ProposedViewSize, e placeSubviews posiciona cada representante de filho dentro de bounds usando place(at:anchor:proposal:).
As propostas carregam dimensões opcionais, bounds pode estar deslocado da origem, e os dois métodos precisam permanecer geometricamente consistentes. A seguir, mediremos as subvisualizações em profundidade.
Perguntas Frequentes
A aula “Noções Básicas do Protocolo Layout” é grátis?
Sim — o texto completo de “Noções Básicas do Protocolo Layout” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.
O que vou aprender em “Noções Básicas do Protocolo Layout”?
Implemente sizeThatFits e placeSubviews. Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Swift Academy?
Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Noções Básicas do Protocolo Layout”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Swift Academy?
Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Noções Básicas do Protocolo Layout
- Medição de Subviews
- Construção de um Layout de Fluxo
- Cache de Layout e Desempenho