ConstraintLayout — o que é, constraints e hierarquia plana

Autor: IT Sectr Publicado: 2026-02-24 Tempo de leitura: 10 min

Entendendo o que é ConstraintLayout — um sistema flexível de posicionamento para Android que permite construir hierarquias planas de views usando constraints (restrições) em vez de LinearLayout e RelativeLayout aninhados. O ConstraintLayout resolve o problema do "aninhamento infernal" (layout nesting hell), reduzindo a profundidade da hierarquia a um único nível e acelerando a renderização da tela. A biblioteca faz parte do Jetpack e está disponível a partir do Android 2.3 (API 9) através da support-library. Os principais mecanismos estão descritos na documentação oficial do Android.

Pontos principais

  • Hierarquia plana — o ConstraintLayout permite construir interfaces de qualquer complexidade sem contêineres aninhados, acelerando onMeasure e onLayout em 2–3 vezes.
  • Constraints — posicionamento de elementos através da vinculação de bordas (layout_constraintLeft_toRightOf, layout_constraintTop_toBottomOf) ao pai ou a outras views.
  • Chain e Guideline — cadeias distribuem elementos uniformemente ou por peso; guias definem margens proporcionais em porcentagens.
  • Barrier e Group — a barreira se ajusta dinamicamente ao tamanho de um grupo de elementos; o Group gerencia a visibilidade de várias views de uma só vez.
  • MotionLayout — uma subclasse do ConstraintLayout para animar transições entre estados de constraints com suporte a KeyFrame.

O que é ConstraintLayout?

ConstraintLayout é um ViewGroup da biblioteca AndroidX ConstraintLayout, projetado para criar interfaces flexíveis e eficientes através de constraints declarativos. Ao contrário do LinearLayout, que organiza elementos em uma linha, ou do RelativeLayout, que posiciona elementos em relação aos vizinhos, o ConstraintLayout permite ancorar cada elemento em relação a qualquer outro elemento e ao pai simultaneamente.

A biblioteca foi anunciada no Google I/O 2016 como uma solução para acelerar a renderização de telas complexas. O principal problema que o ConstraintLayout resolve é o aninhamento de layouts. Cada ViewGroup aninhado adiciona pelo menos duas passadas de measure e uma passada de layout. Uma tela com 4 níveis de aninhamento executa 8 passadas de measure; o ConstraintLayout com a mesma funcionalidade executa apenas 2 passadas. De acordo com o Google (Android Performance Blog, 2017), substituir três LinearLayouts aninhados por um ConstraintLayout reduz o tempo de onMeasure em 40%.

A versão atual ConstraintLayout 2.1.4 funciona de forma estável no Android 2.3+ (API 9) através do AndroidX. A versão 2.0 introduziu o posicionamento circular, o Flow (ajuste automático de elementos) e o suporte ao MotionLayout. O ConstraintLayout é essencial para entender o desenvolvimento moderno do Android — ele é usado no Jetpack Compose como conceito básico de modificadores, nos modelos padrão do Android Studio e no Material Design 3.

Como funciona a hierarquia plana

A hierarquia plana do ConstraintLayout significa que todas as views filhas estão no mesmo nível de aninhamento. Em vez de colocar o elemento A em um LinearLayout, e o LinearLayout em um RelativeLayout, todos os elementos são vinculados diretamente ao ConstraintLayout pai ou uns aos outros através de atributos. Isso proporciona: menor consumo de memória (cada ViewGroup é um objeto no heap Java), layout pass mais rápido (menos chamadas recursivas) e comportamento mais previsível quando os tamanhos de tela mudam.

Sistema de constraints: vinculações, bias e margem

Uma constraint é uma conexão entre a borda de uma View (ou seu centro) e a borda de outra View ou do pai. Cada View pode ter até 8 constraints: left, top, right, bottom, start, end, baseline e center. No mínimo, duas constraints perpendiculares são suficientes para o posicionamento (por exemplo, top + left).

Formato do atributo: app:layout_constraint[Source]_to[Target]Of="[id]" — onde Source é a borda vinculada (Left, Right, Top, Bottom, Start, End, Baseline) e Target é a borda de destino. Exemplo: app:layout_constraintTop_toBottomOf="@+id/header" significa "a borda superior do elemento atual está vinculada à borda inferior do elemento header". Para vincular ao pai, usa-se o id parent.

Bias (viés) é um parâmetro que funciona quando constraints opostos estão presentes (left + right ou top + bottom). Os valores variam de 0 a 1: 0 — pressionado para a borda esquerda/superior, 0.5 — centralizado, 1 — para a borda direita/inferior. Atributos: layout_constraintHorizontal_bias (0.0–1.0) e layout_constraintVertical_bias. As margens são definidas com o padrão android:layout_margin*, mas constraints e margens funcionam de forma independente: a margem é um deslocamento da constraint, não da View vizinha.

Posicionamento percentual

A partir do ConstraintLayout 1.1+, foi adicionado suporte para tamanhos percentuais através de layout_constraintWidth_percent e layout_constraintHeight_percent. Um valor de 0.3 significa 30% da largura/altura do pai. Combinado com bias, isso permite criar layouts adaptativos sem programação.

Chains e Guidelines

Uma Chain (cadeia) é um grupo de duas ou mais Views conectadas por constraints bidirecionais (A está vinculado a B, B está vinculado a A). As cadeias distribuem automaticamente o espaço entre os elementos de acordo com um dos modos: spread (uniformemente, considerando margens), spread_inside (uniformemente, elementos externos sem margem de borda), packed (elementos pressionados com um bias comum). O modo é definido através do atributo app:layout_constraintHorizontal_chainStyle ou layout_constraintVertical_chainStyle.

Uma Guideline (guia) é uma View auxiliar, invisível em tempo de execução, que define uma linha para vinculação. Uma Guideline pode ser horizontal ou vertical, posicionada em dp, porcentagens (app:layout_constraintGuide_percent) ou com um deslocamento da borda (app:layout_constraintGuide_begin/end). As Guidelines são indispensáveis para layouts adaptativos — por exemplo, para dividir a tela em duas metades iguais independentemente do tamanho do dispositivo.

De acordo com o Google I/O 2017, cadeias com spread_inside são 15–20% mais eficientes do que LinearLayouts aninhados com weight, pois evitam a passada dupla de measure necessária para o cálculo do weight.

Barrier, Group e ajudantes virtuais

Uma Barrier (barreira) é uma View virtual que ajusta dinamicamente sua posição com base no tamanho de um grupo de elementos. Ao contrário de uma Guideline com posição fixa, uma Barrier é "empurrada" pelo elemento mais largo do grupo. Por exemplo, se você tem um título e uma descrição com comprimentos desconhecidos, uma Barrier vinculada à borda direita do texto mais largo permite colocar um ícone logo após eles. Atributos: app:barrierDirection (left, right, top, bottom, start, end) e app:constraint_referenced_ids (lista de ids separada por vírgulas).

Group é um contêiner virtual que gerencia a visibilidade de várias Views simultaneamente. Em vez de chamar setVisibility para cada elemento individualmente, basta alterar a visibilidade de um Group. O Group não afeta o posicionamento — apenas a visibilidade. Flow é um ajudante virtual para criar layouts "fluidos": os elementos se ajustam automaticamente para uma nova linha/coluna quando o espaço acaba, como texto em um parágrafo. O Flow suporta wrapMode: none, chain e aligned.

Essas ferramentas (Barrier, Group, Flow, Guideline) são chamadas de ajudantes virtuais porque não são Views no sentido clássico — elas não ocupam espaço na hierarquia e não participam de eventos de foco ou toque. Seu objetivo é simplificar a manutenção de layouts complexos sem adicionar contêineres aninhados.

Exemplos: XML e Kotlin

Exemplo 1: Formulário básico com constraints

Um formulário de login simples com um campo de e-mail, um campo de senha e um botão. Todos os elementos estão vinculados ao pai, exceto o botão — ele está abaixo do campo de senha. É usada uma hierarquia plana — todos os três elementos estão no mesmo nível.

xml
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/email_input"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="32dp"
        android:layout_marginHorizontal="16dp" />

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/password_input"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/email_input"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="16dp" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/password_input"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="24dp"
        android:layout_marginHorizontal="16dp"
        android:text="Entrar" />

</androidx.constraintlayout.widget.ConstraintLayout>

Todos os elementos têm largura de 0dp (match_constraint), o que significa que eles se estendem da constraint start até end considerando as margens horizontais. Isso é equivalente a match_parent com margens, mas sem aninhamento.

Exemplo 2: Cadeia com spread_inside

Três botões distribuídos uniformemente na horizontal com margens de borda. A cadeia spread_inside coloca os botões externos nas bordas e o botão do meio centralizado entre eles.

xml
<Button
    android:id="@+id/btn_left"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/btn_center"
    android:text="Esquerda" />

<Button
    android:id="@+id/btn_center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@+id/btn_left"
    app:layout_constraintRight_toLeftOf="@+id/btn_right"
    android:text="Centro" />

<Button
    android:id="@+id/btn_right"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@+id/btn_center"
    app:layout_constraintRight_toRightOf="parent"
    android:text="Direita" />

A cadeia é criada automaticamente quando os elementos têm constraints bidirecionais. O modo spread_inside é definido em qualquer elemento da cadeia através de app:layout_constraintHorizontal_chainStyle="spread_inside". Isso elimina a necessidade de um LinearLayout com weightSum e layout_weight.

Exemplo 3: Guideline para um layout simétrico

Criação de duas colunas iguais usando uma Guideline vertical a 50%. O elemento esquerdo está vinculado ao pai esquerdo e sua borda direita à guideline; o elemento direito está vinculado com sua borda esquerda à guideline e ao pai direito.

xml
<androidx.constraintlayout.widget.Guideline
    android:id="@+id/gl_midpoint"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

<TextView
    android:id="@+id/left_card"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/gl_midpoint"
    android:layout_margin="8dp"
    android:background="@color/card_background" />

<TextView
    android:id="@+id/right_card"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@+id/gl_midpoint"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_margin="8dp"
    android:background="@color/card_background" />

Uma Guideline com porcentagem de 0.5 se adapta automaticamente à largura da tela. Tanto no tablet quanto no telefone, a proporção das colunas permanece 50/50. Para nomenclatura esquerda/direita, use atributos start/end para compatibilidade RTL.

Comparação: ConstraintLayout vs LinearLayout vs RelativeLayout

Tabela de comparação dos três principais ViewGroups para desenvolvimento Android: ConstraintLayout, LinearLayout e RelativeLayout. Critérios: flexibilidade, desempenho, complexidade do código e casos de uso.

CaracterísticaConstraintLayoutLinearLayoutRelativeLayout
AninhamentoPlano (um nível)Requer aninhamento para layouts complexosUm nível, mas flexibilidade limitada
Desempenho de measure2 passadas (~40% mais rápido)4+ passadas com weight2 passadas
Tamanhos percentuaisSim (guide_percent, width_percent)Apenas via weight/frameNão
Suporte RTLIntegrado (start/end)IntegradoVia start/end (API 17+)
Barrier/Group/FlowSim (ajudantes virtuais)NãoNão
Animações MotionLayoutSimNãoNão
Quando usarTodos os layouts complexos, telas com >5 elementosListas unidirecionais simples, linhas com botõesLayouts relativos simples (código legado)

De acordo com o Android Vitals (Google, 2025), aplicativos que usam ConstraintLayout como contêiner principal mostram em média 18% menos quadros jank ao renderizar telas complexas em comparação com aplicativos que usam LinearLayouts aninhados. Na IT Sectr, mudamos para o ConstraintLayout como padrão para todos os layouts XML em 2018 — isso reduziu a profundidade média da hierarquia da tela de 4.2 para 1.8 níveis e acelerou o desenvolvimento de novos formulários em 25%.

Perguntas frequentes

Qual é a diferença entre match_parent e 0dp (match_constraint) no ConstraintLayout?

match_parent no ConstraintLayout funciona como de costume — estica a View ao tamanho do pai. 0dp (match_constraint) significa que o tamanho da View é calculado a partir das constraints: se as constraints left e right com margens forem definidas, a largura = parent — marginLeft — marginRight. A diferença no comportamento: match_parent ignora o bias e pode transbordar durante a animação; match_constraint respeita corretamente todas as restrições e é recomendado pelo Google como modo principal para ConstraintLayout.

Como criar um layout adaptativo para tablets com ConstraintLayout?

Use uma combinação de: tamanhos percentuais (layout_constraintWidth_percent) para elementos que devem ocupar uma parte da tela; Guideline com porcentagens para dividir a tela em zonas; Barrier para posicionamento em relação a conteúdo dinâmico; Flow com wrapMode para ajustar cartões a uma nova linha. Uma abordagem alternativa é usar SlidingPaneLayout em combinação com ConstraintLayout para interfaces master-detail em tablets.

Posso usar ConstraintLayout no Jetpack Compose?

Jetpack Compose não usa ConstraintLayout como ViewGroup, mas fornece uma versão do ConstraintLayout para compose (androidx.constraintlayout:constraintlayout-compose) com a mesma API em Kotlin DSL: createRefFor(), constrainAs(), linkTo(), chain(), guideFrom(). Isso é útil para layouts complexos que são mais fáceis de descrever através de constraints do que com Column/Row. No entanto, no Compose, recomenda-se começar com Column/Row/Box e passar para ConstraintLayout apenas quando for necessário posicionamento relativo complexo.

Como depurar a sobreposição de elementos no ConstraintLayout?

No Android Studio, abra o Layout Inspector (Tools → Layout Inspector), selecione o aplicativo em execução e passe o cursor sobre o elemento problemático. Você verá todas as constraints, margens, padding e bias em uma representação 3D. Para XML, use o painel Design no editor de layouts — ele destaca conflitos de constraints em amarelo e constraints ausentes em vermelho. No código, certifique-se de que cada View tenha duas constraints perpendiculares, caso contrário, o elemento terminará em (0,0).

Resumo

  • ConstraintLayout — um ViewGroup para layouts Android de hierarquia plana através de constraints declarativos, reduzindo a profundidade de aninhamento a 1 nível.
  • Sistema de constraints — vinculação de bordas ao pai ou outras Views, bias para deslocamento, tamanhos percentuais para adaptabilidade.
  • Cadeias — cadeias com modos spread / spread_inside / packed para distribuir elementos sem contêineres aninhados.
  • Guideline e Barrier — guias fixas e percentuais, e barreiras dinâmicas para posicionamento flexível.
  • Ajudantes virtuais — Group (gerenciamento de visibilidade), Flow (ajuste automático), MotionLayout (animação).
  • Desempenho — 40% mais rápido que LinearLayouts aninhados, 18% menos quadros jank.
  • Escolha — ConstraintLayout para telas complexas, LinearLayout para linhas simples, RelativeLayout apenas em código legado.

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.

Discutir o projeto

Leia também