Como criar uma interface responsiva com o ConstraintLayout Parte do Android Jetpack.

Teste o Compose
O Jetpack Compose é o kit de ferramentas de interface recomendado para Android. Aprenda a trabalhar com layouts no Compose.

A ConstraintLayout permite criar layouts grandes e complexos com uma hierarquia de visualização plana, sem visualização em grupo aninhado. Ele é semelhante a RelativeLayout, em que todas as visualizações são dispostas de acordo com as relações entre visualizações irmãs e o layout pai, mas é mais flexível que RelativeLayout e mais fácil de usar com o Layout Editor do Android Studio.

Todo o poder do ConstraintLayout está disponível diretamente nas ferramentas visuais do Layout Editor, porque a API de layout e o Layout Editor são especialmente criados um para o outro. Você pode criar seu layout com ConstraintLayout arrastando em vez de editar o XML.

Esta página mostra como criar um layout com ConstraintLayout no Android Studio 3.0 ou mais recente. Para mais informações sobre o Layout Editor, consulte Criar uma interface com o Layout Editor.

Para conferir uma variedade de layouts que você pode criar com o ConstraintLayout, consulte o projeto de exemplos de layout restrito no GitHub (link em inglês).

Visão geral sobre restrições

Para definir a posição de uma visualização no ConstraintLayout, adicione pelo menos uma restrição horizontal e uma vertical. Cada restrição representa uma conexão ou alinhamento para outra visualização, o layout pai ou uma diretriz invisível. Cada restrição define a posição da visualização ao longo do eixo vertical ou horizontal. Cada visualização precisa ter no mínimo uma restrição para cada eixo, mas muitas vezes são necessárias mais.

Quando você solta uma visualização no Layout Editor, ela permanece onde você a deixou, mesmo que não tenha restrições. Isso é apenas para facilitar a edição. Se uma visualização não tiver restrições ao executar o layout em um dispositivo, ela será desenhada na posição [0,0] (canto superior esquerdo).

Na Figura 1, o layout parece bom no editor, mas não há restrição vertical na visualização C. Quando esse layout é desenhado em um dispositivo, a visualização C é alinhada horizontalmente com as bordas esquerda e direita da visualização A, mas aparece na parte de cima da tela porque não tem restrição vertical.

Figura 1. O editor mostra a visualização C abaixo de A, mas não tem restrição vertical.

Figura 2. A visualização C agora está verticalmente restrita abaixo da visualização A.

Embora uma restrição ausente não cause um erro de compilação, o Layout Editor indica que restrições ausentes são um erro na barra de ferramentas. Para conferir os erros e outros avisos, clique em Show Warnings and Errors . Para evitar a perda de restrições, o Layout Editor adiciona restrições automaticamente aos recursos Autoconnect and infer constraints.

Adicionar ConstraintLayout ao seu projeto

Para usar ConstraintLayout no seu projeto, faça o seguinte:

  1. Verifique se o repositório maven.google.com foi declarado no arquivo settings.gradle:

    Groovy

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        )
        

    Kotlin

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        }
        
  2. Adicione a biblioteca como uma dependência no arquivo build.gradle do módulo, conforme mostrado no exemplo abaixo. A versão mais recente pode ser diferente da mostrada no exemplo.

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13")
    }
    
  3. Na barra de ferramentas ou na notificação de sincronização, clique em Sync Project with Gradle Files.

Agora você está pronto para criar seu layout com o ConstraintLayout.

Converter um layout

Figura 3. O menu para converter um layout para ConstraintLayout.

Para converter um layout já existente em um layout restrito, siga estas etapas:

  1. Abra o layout no Android Studio e clique na guia Design na parte de baixo da janela do editor.
  2. Na janela Component Tree, clique com o botão direito do mouse no layout e clique em Convert LinearLayout to ConstraintLayout.

Criar um novo layout

Para iniciar um novo arquivo de layout restrito, siga estas etapas:

  1. Na janela Project, clique na pasta do módulo e selecione File > New > XML > Layout XML.
  2. Insira um nome para o arquivo de layout e insira "androidx.constraintlayout.widget.ConstraintLayout" para a tag raiz.
  3. Clique em Finish.

Adicionar ou remover uma restrição

Para adicionar uma restrição, faça o seguinte:

Vídeo 1. O lado esquerdo de uma visualização é restrito ao lado esquerdo do pai.

  1. Arraste uma visualização da janela Palette para o editor.

    Quando você adiciona uma visualização a um ConstraintLayout, ela é exibida em uma caixa delimitadora com alças quadradas de redimensionamento em cada canto e alças circulares em cada lado.

  2. Clique na visualização para selecioná-la
  3. Escolha uma destas opções:
    • Clique em uma alça de restrição e arraste-a para um ponto de fixação disponível. Esse ponto pode ser a borda de outra visualização, a borda do layout ou uma linha guia. Observe que, conforme você arrasta a alça de restrição, o Layout Editor mostra possíveis âncoras de conexão e sobreposições azuis.
    • Clique em um dos botões Create a connection na seção Layout da janela Attributes, como mostrado na Figura 4.

      Figura 4. A seção Layout da janela Attributes permite criar conexões.

Quando a restrição é criada, o editor fornece uma margem padrão para separar as duas visualizações.

Ao criar restrições, lembre-se das seguintes regras:

  • Cada visualização precisa ter pelo menos duas restrições: uma horizontal e uma vertical.
  • Só é possível criar restrições entre uma alça de restrição e um ponto de fixação que compartilham o mesmo plano. Um plano vertical (os lados esquerdo e direito) de uma visualização pode ser restrito apenas a outro plano vertical, e as linhas de base só podem ser restritas a outros valores de referência.
  • Cada identificador de restrição pode ser usado para apenas uma restrição, mas você pode criar várias restrições de diferentes visualizações para o mesmo ponto de fixação.

Você pode excluir uma restrição realizando uma das seguintes ações:

  • Clique em uma restrição para selecioná-la e, em seguida, clique em Excluir.
  • Com a tecla Control pressionada, clique (Command e clique no macOS) em uma âncora de restrição. A restrição fica vermelha para indicar que você pode clicar para excluí-la, como mostrado na Figura 5.

    Figura 5. Uma restrição vermelha indica que você pode clicar para excluí-la.

  • Na seção Layout da janela Attributes, clique em um ponto de fixação de restrição, como mostrado na Figura 6.

    Figura 6. Clique em um ponto de fixação de restrição para excluí-la.

Vídeo 2. Adição de uma restrição que se opõe a uma já existente.

Se você adicionar restrições opostas a uma visualização, as linhas de restrição vão ficar enroladas como uma mola para indicar as forças opostas, como mostrado no vídeo 2. O efeito fica mais visível quando o tamanho da visualização é definido como "fixo" ou "wrap content". Nesse caso, a visualização está centralizada entre as restrições. Se você quiser que a visualização estenda o tamanho para atender às restrições, mude o tamanho para "match constraints". Se você quiser manter o tamanho atual, mas mover a visualização para que ela não fique centralizada, ajuste o viés de restrição.

Você pode usar restrições para alcançar diferentes tipos de comportamento de layout, conforme descrito nas seções a seguir.

Posição do pai

Restringir a lateral de uma visualização à borda correspondente do layout.

Na Figura 7, o lado esquerdo da visualização está conectado à borda esquerda do layout pai. Você pode definir a distância a partir da borda com margem.

Figura 7. Uma restrição horizontal ao pai.

Posição da ordem

Defina a ordem de exibição de duas visualizações, vertical ou horizontalmente.

Na figura 8, B está restrito a ficar sempre à direita de A, e C está restrito abaixo de A. No entanto, essas restrições não implicam alinhamento, então B ainda pode se mover para cima e para baixo.

Figura 8. Uma restrição horizontal e vertical.

Alinhamento

Alinhe a borda de uma visualização com a mesma borda de outra.

Na figura 9, o lado esquerdo de B está alinhado com o lado esquerdo de A. Se você quiser alinhar os centros de visualização, crie uma restrição em ambos os lados.

Você pode deslocar o alinhamento arrastando a visualização para dentro a partir da restrição. Por exemplo, a figura 10 mostra B com um alinhamento de deslocamento de 24 dp. O deslocamento é definido pela margem da visualização restrita.

Você também pode selecionar todas as visualizações que quer alinhar e, em seguida, clicar em Align na barra de ferramentas para selecionar o tipo de alinhamento.

Figura 9. Uma restrição de alinhamento horizontal.

Figura 10. Uma restrição de deslocamento de alinhamento horizontal.

Alinhamento da linha de base

Alinhe a linha de base do texto de uma visualização à linha de base do texto de outra.

Na figura 11, a primeira linha de B está alinhada com o texto em A.

Para criar uma restrição de valor de referência, clique com o botão direito do mouse na visualização de texto que você quer restringir e clique em Show Baseline. Em seguida, clique na linha de base do texto e arraste a linha para outra linha de base.

Figura 11. Uma restrição de alinhamento de valor de referência.

Restringir a uma linha guia

Você pode adicionar uma linha guia vertical ou horizontal que permita restringir as visualizações e que fique invisível para os usuários do app. Você pode posicionar a linha guia no layout com base em unidades dp ou em uma porcentagem relativa à borda do layout.

Para criar uma diretriz, clique em Guidelines na barra de ferramentas e depois clique em Add Vertical Guideline ou Add Horizontal Guideline.

Arraste a linha pontilhada para reposicionar e clique no círculo na borda da linha guia para alternar o modo de medição.

Figura 12. Uma visualização restrita a uma diretriz.

Restringir a uma barreira

Semelhante a uma diretriz, uma barreira é uma linha invisível a que você pode restringir visualizações, mas não define a própria posição. Em vez disso, a posição da barreira se move com base na posição das visualizações contidas nela. Isso é útil quando você quer restringir uma visualização a um conjunto em vez de uma específica.

Por exemplo, na Figura 13, a visualização C está restrita ao lado direito de uma barreira. A barreira é definida como o "fim" (ou o lado direito, em um layout da esquerda para a direita) da visualização A e da visualização B. A barreira se move dependendo se o lado direito da visualização A ou da visualização B está mais à direita.

Para criar uma barreira, siga estas etapas:

  1. Clique em Guidelines na barra de ferramentas e depois clique em Add Vertical Barrier ou Add Horizontal Barrier.
  2. Na janela Component Tree, selecione as visualizações que você quer dentro da barreira e arraste-as para o componente de barreira.
  3. Selecione a barreira na Component Tree, abra a janela Attributes e defina barrierDirection.

Agora você pode criar uma restrição de outra visualização para a barreira.

Você também pode restringir à barreira as visualizações que estão dentro da barreira. Dessa forma, é possível alinhar todas as visualizações na barreira entre si, mesmo que você não saiba qual é a mais longa ou a mais alta.

Você também pode incluir uma diretriz dentro de uma barreira para garantir uma posição "mínima" para ela.

Figura 13. A visualização C está restrita a uma barreira, que se move com base na posição e no tamanho da visualização A e da visualização B.

Ajustar o viés da restrição

Quando você adiciona uma restrição a ambos os lados de uma visualização e o tamanho da visualização da mesma dimensão é "fixo" ou "conteúdo unido", a visualização fica centralizada entre as duas restrições com um viés de 50% por padrão. Para ajustar o viés, arraste o controle deslizante na janela Attributes ou arraste a visualização, como mostrado no vídeo 3.

Se você quiser que a visualização estenda o tamanho para atender às restrições, mude o tamanho para "match constraints".

Vídeo 3. Ajuste o viés da restrição.

Ajustar o tamanho da visualização

Figura 14. Ao selecionar uma visualização, a janela Attributes inclui controles para 1 proporção de tamanho, 2 exclusão de restrições, 3 modo de altura ou largura, 4 margens e 5 viés de restrição. Você também pode destacar restrições individuais no Layout Editor clicando nelas na lista de restrições 6.

Você pode usar as alças dos cantos para redimensionar uma visualização, mas isso vai fixar o tamanho no código: a visualização não será redimensionada para diferentes conteúdos ou tamanhos de tela. Para selecionar outro modo de dimensionamento, clique em uma visualização e abra a janela Attributes no lado direito do editor.

Próximo à parte de cima da janela Attributes, está o inspetor de visualização, que inclui controles para vários atributos de layout, como mostrado na Figura 14. Essa opção está disponível apenas para visualizações em um layout restrito.

É possível mudar a forma como a altura e a largura são calculadas clicando nos símbolos indicados pela frase de destaque 3 na figura 14. Esses símbolos representam o modo de tamanho da seguinte maneira: Clique no símbolo para alternar entre essas configurações:

  • Fixo: especifique uma dimensão específica na caixa de texto a seguir ou redimensione a visualização no editor.
  • Ajustar conteúdo: a visualização se expande somente o necessário para ajustar o conteúdo.
    • layout_restrictedWidth (link em inglês)
    • Defina como true para permitir que a dimensão horizontal mude para respeitar as restrições. Por padrão, um widget definido como WRAP_CONTENT não é limitado por restrições.

  • Match Constraints: a visualização se expande o máximo possível para atender às restrições de cada lado, depois de contabilizar as margens da visualização. No entanto, você pode modificar esse comportamento com os atributos e valores abaixo. Esses atributos só entram em vigor quando você define a largura da visualização como "match constraints":
    • layout_constraintWidth_min (link em inglês)

      Isso leva uma dimensão dp para a largura mínima da visualização.

    • layout_constraintWidth_max (em inglês)

      Isso leva uma dimensão dp para a largura máxima da visualização.

    No entanto, se a dimensão especificada tiver apenas uma restrição, a visualização se expandirá para ajustar o conteúdo. Usar esse modo na altura ou na largura também permite definir uma proporção de tamanho.

Definir o tamanho como uma proporção

Figura 15. A visualização é definida como uma proporção de 16:9 com a largura com base em uma proporção da altura.

Você pode definir o tamanho da visualização como uma proporção, como 16:9, se pelo menos uma das dimensões estiver definida como "corresponder restrições" (0dp). Para ativar a proporção, clique em Alternar restrição de proporção (frase de destaque 1 na Figura 14) e insira a proporção width:height na entrada exibida.

Se a largura e a altura estiverem definidas como "match constraints", clique em Toggle Aspect Ratio Constraint para selecionar qual dimensão é baseada em uma proporção da outra. O inspetor de visualização indica qual dimensão é definida como uma proporção conectando as bordas correspondentes a uma linha sólida.

Por exemplo, se você definir ambos os lados como "match constraints", clique em Toggle Aspect Ratio Constraint duas vezes para definir a largura como uma proporção da altura. O tamanho total é determinado pela altura da visualização, que pode ser definida de qualquer forma, como mostrado na Figura 15.

Ajustar as margens da visualização

Para tornar suas visualizações espaçadas uniformemente, clique em Margin na barra de ferramentas para selecionar a margem padrão para cada visualização adicionada ao layout. Qualquer mudança feita na margem padrão se aplica apenas às visualizações adicionadas a partir de então.

Você pode controlar a margem de cada visualização na janela Attributes clicando no número na linha que representa cada restrição. Na Figura 14, a frase de destaque 4 mostra que a margem inferior está definida como 16 dp.

Figura 16. O botão Margin da barra de ferramentas.

Todas as margens oferecidas pela ferramenta são fatores de 8 dp para ajudar as visualizações a se alinharem às recomendações de grade quadrada de 8 dp do Material Design.

Controlar grupos lineares com uma cadeia

Figura 17. Uma cadeia horizontal com duas visualizações.

Uma cadeia é um grupo de visualizações vinculadas umas às outras com restrições de posição bidirecional. As visualizações em uma cadeia podem ser distribuídas vertical ou horizontalmente.

Figura 18. Exemplos de cada estilo de cadeia.

As cadeias podem ser estilizadas de uma das seguintes maneiras:

  1. Spread: as visualizações são distribuídas uniformemente depois que as margens são contabilizadas. Esse é o padrão.
  2. Distribuição interna:a primeira e a última visualização são fixadas nas restrições de cada extremidade da cadeia, e o restante é distribuído uniformemente.
  3. Ponderado:quando a cadeia é definida como spread ou spread inside, você pode preencher o espaço restante definindo uma ou mais visualizações como "match constraints" (0dp). Por padrão, o espaço é distribuído uniformemente entre cada visualização definida como "match constraints", mas é possível atribuir uma ponderação de importância para cada visualização usando os atributos layout_constraintHorizontal_weight e layout_constraintVertical_weight. Isso funciona da mesma forma que layout_weight em um layout linear: a visualização com o maior valor de ponderação ocupa mais espaço, e visualizações com o mesmo peso têm a mesma quantidade de espaço.
  4. Empacotado:as visualizações são agrupadas depois que as margens são contabilizadas. É possível ajustar o viés de toda a cadeia (esquerda, direita, para cima ou para baixo) mudando o viés de visualização "principal" da cadeia.

A visualização "head" da cadeia (a visualização mais à esquerda em uma cadeia horizontal (em um layout da esquerda para a direita) e a visualização mais superior em uma cadeia vertical) define o estilo da cadeia em XML. No entanto, é possível alternar entre spread, spread inside e pack selecionando qualquer visualização na cadeia e clicando no botão de cadeia que aparece abaixo da visualização.

Para criar uma rede, faça o seguinte, como mostrado no vídeo 4:

  1. Selecione todas as visualizações a serem incluídas na cadeia.
  2. Clique com o botão direito do mouse em uma das visualizações.
  3. Selecione Redes.
  4. Selecione Center Horizontally ou Center Vertically.

Vídeo 4. Criação de uma cadeia horizontal.

Confira alguns pontos a serem considerados ao usar cadeias:

  • Uma visualização pode fazer parte de uma cadeia vertical e horizontal, portanto, você pode criar layouts de grade flexíveis.
  • Uma cadeia só funciona corretamente se cada extremidade dela estiver restrita a outro objeto no mesmo eixo, como mostrado na Figura 14.
  • Embora a orientação de uma cadeia seja vertical ou horizontal, o uso de uma não alinha as visualizações nessa direção. Para alcançar a posição adequada para cada visualização na cadeia, inclua outras restrições, como restrições de alinhamento.

Criar restrições automaticamente

Em vez de adicionar restrições a todas as visualizações à medida que elas são colocadas no layout, é possível mover cada visualização para as posições desejadas no Layout Editor e clicar em Infer Constraints para criar restrições automaticamente.

Infer Constraints verifica o layout para determinar o conjunto de restrições mais eficaz para todas as visualizações. Ela restringe as visualizações às posições atuais e fornece flexibilidade. Pode ser necessário fazer ajustes para que o layout responda conforme pretendido para diferentes tamanhos e orientações de tela.

Autoconnect to Parent é um recurso separado que você pode ativar. Quando ele está ativado e você adiciona visualizações filhas a uma visualização mãe, esse recurso cria automaticamente duas ou mais restrições para cada visualização à medida que elas são adicionadas ao layout, mas somente quando é adequado restringir a visualização ao layout pai. A conexão automática não cria restrições a outras visualizações no layout.

O recurso de conexão automática fica desativado por padrão. Ative-a clicando em Enable Autoconnection to Parent na barra de ferramentas do Layout Editor.

Animações de frames-chave

Em uma ConstraintLayout, você pode animar mudanças no tamanho e na posição dos elementos usando ConstraintSet e TransitionManager.

Um ConstraintSet é um objeto leve que representa as restrições, margens e padding de todos os elementos filhos em uma ConstraintLayout. Quando você aplica uma ConstraintSet a uma ConstraintLayout exibida, o layout atualiza as restrições de todos os filhos.

Para criar uma animação usando ConstraintSet, especifique dois arquivos de layout que funcionam como frames-chave de início e fim. Em seguida, você pode carregar um ConstraintSet do segundo arquivo de frame-chave e aplicá-lo ao ConstraintLayout exibido.

O exemplo de código abaixo mostra como animar movendo um único botão para a parte de baixo da tela.

// MainActivity.kt

fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.keyframe_one)
    constraintLayout = findViewById(R.id.constraint_layout) // member variable
}

fun animateToKeyframeTwo() {
    val constraintSet = ConstraintSet()
    constraintSet.load(this, R.layout.keyframe_two)
    TransitionManager.beginDelayedTransition()
    constraintSet.applyTo(constraintLayout)
}
// layout/keyframe1.xml
// Keyframe 1 contains the starting position for all elements in the animation
// as well as final colors and text sizes.

<?xml version="1.0" encoding="utf-8"?>
<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">

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
// layout/keyframe2.xml
// Keyframe 2 contains another ConstraintLayout with the final positions.

<?xml version="1.0" encoding="utf-8"?>
<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">

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Outros recursos

ConstraintLayout é usado no app de demonstração Sunflower.