ConstraintLayout, Melhor Performance no Android

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /ConstraintLayout, Melhor Performance no Android

ConstraintLayout, Melhor Performance no Android

Vinícius Thiengo
(13666) (13)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloManual de DevOps: como obter agilidade, confiabilidade e segurança em organizações tecnológicas
CategoriaEngenharia de Software
Autor(es)Gene Kim, Jez Humble, John Willis, Patrick Debois
EditoraAlta Books
Edição
Ano2018
Páginas464
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Tudo bem?

Neste artigo vamos estar apresentando o ConstraintLayout do Android, um layout muito similar ao RelativeLayout, porém ainda mais flexível fazendo com que nós, developers Android, possamos evitar ainda mais os layouts aninhados.

Ai você pergunta: qual o problema em aninhar layouts?

O custo da renderização é maior, na maioria dos casos. Além de ser fonte de problemas de layout sendo utilizado sem necessidade, por exemplo.

Para melhor estudo sobre layouts e aninhamento entre esses, acesse essa página da documentação Android: Optimizing Layout Hierarchies.

Antes de prosseguir, não esqueça de se inscrever 📫na lista de e-mails do Blog para receber, em primeira mão, todos os conteúdos Android exclusivos do Blog.

No decorrer do conteúdo vamos abordar:

Configuração Android Studio

Essa é primeira vez, dentre os artigos do Blog, que houve a necessidade de instalar um novo Android Studio. Com a versão 2.1 ou menor você não conseguirá utilizar o ConstraintLayout, ao menos não com o novo UI Builder do Android Studio.

Pode parecer estranho, mas o ConstraintLayout e o Android Studio estão relacionados a ponto de que se um evolui o outro tende a evoluir também, digo, ambos, provavelmente, terão atualização de versão.

Antes de rodar os exemplos corretamente tive alguns problemas em utilizar o Android Studio 2.2 Preview 2 (clique no link para download) com a versão Alpha 4 do ConstraintLayout.

Qual tipo de problema?

Mais precisamente: a margem para widgets e layout (o ConstraintLayout) não funcionava, ao menos para o lado direito do ConstraintLayout. Outro bug era com as linhas dos widgets, essas atualizavam de posição, porém o conteúdo não.

Logo a solução foi utilizar a última versão disponível da library do ConstraintLayout, porém não foi trivial descobrir sobre a última versão. Nos principais tutoriais encontrados (primeiros resultados do Google) não há nada sobre ela.

Depois de já descarregada e instalada ao menos a versão 2.2 Preview 2 do Android Studio (isso mesmo, somente a atualização desse IDE via update option não funciona, você terá de baixar tudo novamente), clique no ícone do SDK Manager:

Ícone Android Studio do SDK Manager

Então clique na aba SDK Tools e em seguida dê um check em ConstraintLayout for Android e clique em Apply

Janela Android Studio de Preferências Padrões de SDK

Com isso você já poderá seguir com a versão mais estável (até a data desse post) do Android Studio e ConstraintLayout, e acredite, funciona sem problema algum (ao menos não evidente quanto na versão Alpha 4 do ConstraintLayout).

Antes de prosseguir com o código de exemplo você deve estar se perguntando: versão Alpha? É isso mesmo? Podemos já utilizar em produção?

Na documentação do ConstraintLayout não há nada informando para não utilizarmos mesmo que em Alpha. Até a versão Alpha 4 eu poderia seguramente lhe informar para nem mesmo testar devido a quantidade de bugs, incluindo os do UI Builder.

Porém com a versão Alpha 7, a princípio, está tudo ok. Sério! Inclusive no vídeo, logo no final do artigo, realizo vários testes mostrando o perfeito funcionamento do layout.

Obviamente que sabemos o risco que é utilizar uma versão Alpha, logo, depois de implementar em seu aplicativo, realize ao menos os testes mais óbvios para seu domínio do problema para depois decidir se vale ou não a pena colocar em produção com o novo layout.

Com isso podemos seguir para o código de exemplo.

Codificação necessária para utilizar o ConstraintLayout

A partir desse ponto, além dos códigos do projeto de exemplo vamos também estudar alguns pontos chaves do ConstraintLayout e do novo UI Builder do Android Studio.

Note que o Constraint do nome do layout é referente as restrições (ou limitações ou especificações) que podemos adicionar aos widgets (Views) dentro desse layout.

É possível utilizar o ConstraintLayout a partir da API 9, Android 2.3 (Gingerbread).

Vamos começar configurando o Gradle top level, build.gradle (Project: constraint-layout-start). Verifique se o seu está com configurações similares:

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0-rc1'
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

 

Pode ser que o seu classpath esteja com uma versão diferente. Tente rodar o projeto mesmo assim, pois tentei somente com a versão acima. Caso surjam problemas, altere como para utilizar a versão indicada aqui.

Agora vamos ao Gradle App level, build.gradle (Module: app). Aqui somente as dependências são atualizadas:

apply plugin: 'com.android.application'

android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
applicationId "com.google.googleio"
minSdkVersion 22
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha7' /* ADICIONE ESSA LINHA */
testCompile 'junit:junit:4.12'
}

 

Agora os códigos, na verdade, os passos no UI Builder do Android Studio. Devido a melhora no UI Builder é muito mais tranquilo utiliza-lo para a construção do layout do que diretamente codificar no XML.

Nesse início ainda vamos no código XML. Clique na aba Text e crie um layout chamado activity_main_update.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main_update"
android:layout_width="match_parent"
android:layout_height="match_parent">

</android.support.constraint.ConstraintLayout>

 

No UI Builder, depois de clicar na aba Design, você terá algo similar a isso:

Área de design de layout do Android Studio

Antes de prosseguir certifique-se de que o Autoconnect esteja bloqueado, logo nas ferramentas do UI Builder verifique se há o seguinte ícone:

Ícone de Autoconnect

Caso sim, clique nele para ficar da seguinte forma:

Ícone de Autoconnect com bloqueio

No decorrer do artigo vamos falar dessa opção, Autoconnect.

Agora no menu de Views lateral vá até Images & Medias, então clique e arraste para o device com o ConstraintLayout o item ImageView.

Caso tenha baixado o projeto deste artigo, selecione a imagem singapore assim que o dialog de imagens aparecer, caso contrário selecione qualquer uma. Depois deste passo terá algo como:

Janela de design com uma imagem definida

O primeiro (são três) constraint que iremos utilizar é o Resize Handle, representado pelos retângulos nos limites dos widgets no layout:

Resize Handle

Com esse constraint é possível redimensiona-los, logo vamos colocar o ImageView em um tamanho melhor para trabalhar o layout e então posiciona-lo mais acima. Agora temos:

ImageView melhor dimensionado no ConstraintLayout

Note ao lado, na aba Properties, há as medições, largura e altura, exatas do ImageView. Com essa aba é possível acessar e alterar todos os atributos do widget. 

Clicando em View all properties acessamos o restante dos atributos:

Janela de design com a aba View all properties aberta

Nosso próximo passo é definir o atributo scaleType do ImageView com o valor centerCrop, como abaixo:

Propriedades do ImageView

Agora podemos começar as vinculações do ImageView ao ConstraintLayout para que seja possível centralizar o widget no topo da tela.

Para isso vamos utilizar um outro constraint, Side Constraint Handle:

Side Constraint Handle

Clique no Side Handle de topo do ImageView e arraste até o topo do ConstraintLayout, assim que ficar com a bolinha verde, solte o clique:

Reposicionando o ImageView

Agora vamos repetir o processo para o Left Side Handle e para o Right Side Handle do ImageView, respectivamente ligando esses aos handles Left e Right (esquerdo e direito) do ConstraintLayout.

Logo teremos:

Reposicionando o ImageView dentro do ConstraintLayout

Ao lado, em Properties, logo no topo temos algumas definições importantes do widget que está sendo trabalhado, o ImageView:

Valores de propriedades do ImageView em tela

O quadrado mais escuro ao centro representa o widget. As linhas dentro dele representam como serão trabalhadas as largura e altura, podendo essas terem as seguintes configurações:

  • Fixed: O tamanho fixo e definido em DPs;
  • Any Size: O widget terá o tamanho atualizado para ocupar os espaços em branco existentes entre as constraints (Side Handle) do eixo escolhido (esse é mais tranquilo de entender na prática). Não confunda o Any Size com o MATCH_PARENT, pois não são a mesma coisa;
  • Wrap Content: mais comum com widget de texto. O tamanho será o suficiente para comportar o conteúdo.

Note que os tamanhos na vertical e horizontal podem ter tipos distintos de trabalho no widget, um pode ser Fixed e o outro Any Size, por exemplo.

As linhas externas ao quadrado mais escuro e com números ao lado representam as margens que o widget está utilizando para com widgets vizinhos ou até mesmo com o ConstraintLayout, caso do ImageView.

A Horizontal Bias somente está presente, pois o ImageView está com as constraints Side Handle da esquerda e direita sendo utilizadas, ou seja, permitindo que o widget seja movimentado na horizontal (eixo x), caso contrário o Horizontal Bias não apareceria.

Side Handle

Como teste, ligue também o Bottom Side Handle do ImageView ao Bottom Side Handle do ConstraintLayout e teste os movimentos no Vertical e Horizontal Bias.

Depois dos testes com os Bias como indicado acima, vamos as novas configurações do widget ImageView. Coloque a largura dele como WRAP_CONTENT. A altura como 203dp (essa escolha foi aleatória).

No quadrado interno clique nas linhas horizontais que estão como Fixed para colocá-las como Any Size. E para todas as margens coloque o valor 0. Assim temos:

ImageView com margens iguais a 0dp

Note que se você realizou os testes com os Bias Vertical e Horizontal, já pode remover o Bottom Side Handle do ImageView com o ConstraintLayout apenas clicando nesse Side Handle do ImageView.

Aproveitando o assunto "remove constraint", outras duas formas são via Remove Icon no widget:

Remove Icon

Clicando nele todas as constraints definidas para o widget, digo, as Side Handle, serão removidas.

Logo no topo do UI Builder, tem um Remove Icon, clicando nele (se fizer isso, depois volte com as constraints colocadas até aqui) você irá remover todos os constraints do layout atual.

Remove Icon em menu de janela de design

Note que estou trabalhando no Blue Print, mas é possível realizar as mesmas alterações de layout na tela real simulada ao lado da Blue Print.

Com isso podemos ver como se encontra o XML do layout. Logo abaixo no UI Builder clique na aba Text:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:src="@drawable/singapore"
android:layout_width="wrap_content"
android:layout_height="203dp"
android:id="@+id/imageView8"
android:scaleType="centerCrop"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>

 

Os atributos de ligação em ImageView são bem intuitivos, layout_constraintTop_toTopOf="parent", por exemplo, indica a ligação do topo do ImageView com o topo do ConstraintLayout, que nesse caso é o parent.

Caso fosse uma ligação com outro widget seria o id do widget o conteúdo do atributo.

Agora no topo do UI Builder clique no ícone do Autoconnect (voltamos!) para ativá-lo:

Ícone de Autoconnect em bloqueio

Logo depois, na aba de Views, clique e arraste um TextView logo para baixo do ImageView. Note as constraints sendo ligadas automaticamente:

TextView abaixo do ImageView em ConstraintLayout

O Autoconnect é uma funcionalidade que tem como objetivo realizar as conexões mais eficientes para o widget selecionado, isso de forma automática.

Porém (provavelmente devido a versão Alpha) não obtive bons resultados com ele ativado. Logo clique novamente no ícone do Autoconnect para desativá-lo e remova todas as constraints criadas para o TextView.

Deixe o TextView ainda no layout, somente remova as constraints dele clicando no icon de remoção de constraints desse widget.

Agora realize as seguintes alterações no TextView:

  • Side Handle: Ligue o topo dele com o bottom do ImageView;
  • Side Handle: Ligue o lado esquerdo dele com o lado esquerdo do ConstraintLayout (parent);
  • Na aba Properties, mais precisamente no quadrado central, clique nas linhas verticais que estão como Fixed. Clique duas vezes até ficarem como Wrap Content;
  • Logo abaixo, em layout_width, coloque 156dp;
  • Então em text, coloque um texto grande, como: "It is a common misconception that using the basic layout structures leads to the most efficient layouts. However, each widget and layout you add to your application requires initialization, layout, and drawing".

Logo depois você deverá ter algo como:

TextView com conteúdo e redimensionado

E a seguinte nova configuração no XML do layout:

<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
...

<TextView
android:text="..."
android:layout_width="156dp"
android:layout_height="wrap_content"
android:id="@+id/textView19"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/imageView8"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toLeftOf="parent" />
</android.support.constraint.ConstraintLayout>

 

Note que o TextView já tem configurado uma margem top e left, provavelmente em seu caso também estará, respectivamente, 8dp e 16dp.

Esses valores estão seguindo as especificações do Material Design Android. Caso estejam diferentes, logo em Properties os altere para terem os valores 8 para margem de topo e 16 para margem esquerda.

Agora na aba de Views, vá até Text Fields, clique e arraste o item Plain Text para ficar ao lado do TextView.

Ainda sem nenhuma constraint criada para o novo widget, vá até os ícones de topo do UI Builder e clique em Infer Constraints:

Ícone Infer Constraints

Logo depois coloque o cursor do mouse em cima do widget adicionado e veja que alguns constraints foram criados automaticamente.

Constraints criados automaticamente

Essa funcionalidade de inferência tenta fazer o que o Autoconnect faz com o widget, porém o Infer Constraint realiza a tarefa com todos os widgets ainda sem conexão.

Como no Autoconnect percebi que as ligações realizadas não foram mais eficientes que as que fiz na mão. Logo, remova as conexões criadas para o Plain Text e então realize as seguintes alterações nele:

  • Side Handle: Ligue o topo dele com o bottom do ImageView;
  • Side Handle: Ligue o lado esquerdo dele com o lado esquerdo do TextView;
  • Side Handle: Ligue o lado direito dele com o lado direito do ConstraintLayout;
  • Na aba Properties, mais precisamente no quadrado central, clique nas linhas horizontais que estão como Fixed. Clique uma vez para ficar como Any Size;
  • Agora, nas linhas de margens esquerda, topo e direita do widget coloque respectivamente os valores: 16, 8 e 16.

Depois dessas atualizações no Plain Text, seu layout estará como:

Novo TextView adicionado em layout

E no XML terá um novo widget:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

...

<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="Name"
android:ems="10"
android:id="@+id/editText7"
android:layout_marginStart="16dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toRightOf="@+id/textView19"
android:layout_marginEnd="16dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.46"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/imageView8" />
</android.support.constraint.ConstraintLayout>

 

Agora para completar o layout vamos adicionar outros widgets.

Na aba de Views, clique em TextView. Agora arraste para logo abaixo do Plain Text. Em seguida coloque as seguintes configurações:

  • Side Handle: Ligue o topo dele com o bottom do Plain Text;
  • Side Handle: Ligue o lado esquerdo dele com o lado esquerdo do TextView adicionado inicialmente;
  • Side Handle: Ligue o lado direito dele com o lado direito do ConstraintLayout;
  • Na aba Properties, mais precisamente no quadrado central, clique nas linhas horizontais que estão como Fixed. Clique uma vez para ficar como Any Size;
  • Agora nas linhas verticais do mesmo quadrado do passo acima, clique até ficar com o tipo Wrap Content;
  • Nas linhas de margens esquerda, topo e direita do widget coloque respectivamente os valores: 16, 8 e 16;
  • Logo abaixo na aba Properties, em text, coloque: "The Android SDK tools include a tool called Hierarchy Viewer that allows you to analyze your layout while your application is running.".

Com isso agora temos o seguinte layout:

Mais um TextView adicionado em layout

Assim temos o novo widget no XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

...

<TextView
android:text="The Android SDK tools include a tool called Hierarchy Viewer that allows you to analyze your layout while your application is running."
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textView20"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/editText7"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toRightOf="@+id/textView19"
android:layout_marginEnd="16dp"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>

 

Agora, novamente na aba de Views, na seção Widgets, clique e arraste um Button para o canto inferior direito do layout. Logo depois coloque as seguintes configurações:

  • Side Handle: Ligue o topo dele com o bottom do último TextView adicionado;
  • Side Handle: Ligue o bottom dele com o bottom do ConstraintLayout;
  • Side Handle: Ligue o lado direito dele com o lado direito do ConstraintLayout;
  • Na aba Properties, mais precisamente no quadrado central, clique nas linhas horizontais e verticais até ambas ficarem com o tipo Wrap Content, isso se já não estiverem assim;
  • Ainda na aba Properties, vá no Vertical Bias e arraste para baixo o ícone até atingir o valor 0;
  • Agora, nas linhas de margens topo, direita e fundo do widget coloque respectivamente os valores: 8, 16 e 16.

Aproveitando o embalo, adicione outro Button, agora ao lado do Button adicionado anteriormente. Dessa vez as configurações serão:

  • Side Handle: Ligue o bottom dele com o bottom do ConstraintLayout;
  • Side Handle: Ligue o lado direito dele com o lado direito do Button adicionado anteriormente;
  • Na aba Properties, mais precisamente no quadrado central, clique nas linhas horizontais e verticais até ambas ficarem com o tipo Wrap Content;
  • Agora, nas linhas de margens direita e fundo do widget coloque respectivamente os valores: 16 e 8.

Fique atento nas configurações do último Button adicionado, pois elas não são as mesmas que a do primeiro Button, aliás algumas configurações não são nem mesmo necessárias.

Notei isso. Por que as configurações de margem de topo e constraint de topo não são necessárias nesse widget?

Porque essas configurações já estão no primeiro Button adicionado. Essas servem somente para manter os Buttons do layout abaixo do TextView que o primeiro Button está conectado.

Caso contrário, assim que o device for colocado em modo Landscape os Buttons teriam grandes chances de ficarem sobre o TextView.

Com os novos widgets adicionados agora temos o seguinte layout:

Dois novos Buttons adicionados em layout

E a seguinte nova configuração no arquivo XML de layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

...

<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button11"
android:layout_marginEnd="16dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/textView20"
app:layout_constraintVertical_bias="1.0" />

<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button12"
app:layout_constraintRight_toLeftOf="@+id/button11"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp" />
</android.support.constraint.ConstraintLayout>

 

Agora para abordar o último constraint Side Handle vamos adicionar um novo widget, um TextView. Coloque-o logo no canto inferior esquerdo do layout.

Expanda o Textview utilizando o constraint Resize Handle deixando ele com o tamanho aproximado a 83x41 dp. Logo depois note o ícone de nosso terceiro constraint, Baseline Handle:

Baseline Handle

Deixe o cursor do mouse alguns segundos parado em cima desse ícone e assim que ele começar a piscar clique e arraste a seta para o baseline do último Button adicionado, assim que fixar solte ele, como abaixo:

Baseline constraint para os Buttons

Agora podemos seguir com as demais configurações:

  • Side Handle: Ligue o lado esquerdo dele com o lado esquerdo do ConstraintLayout;
  • Em Properties clique nas linhas verticais e horizontais dentro do quadrado mais escuro até que elas fiquem com o tipo Wrap Content;
  • Ainda em Properties, na margem referente ao lado esquerdo do ConstraintLayout coloque o valor 16.

Com essa nova atualização temos o novo layout:

Último TextView em baseline com os Buttons de fundo

E então o novo widget no XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

...

<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView21"
app:layout_constraintBaseline_toBaselineOf="@+id/button12"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toLeftOf="parent" />
</android.support.constraint.ConstraintLayout>

 

Para que seja possível rodar sem problemas também em Landscape, mais precisamente para que tenha o scroll de tela, devemos adicionar o ScrollView no layout, logo faça a seguinte alteração no XML:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">

<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

...

</android.support.constraint.ConstraintLayout>
</ScrollView>

 

Agora executando o projeto temos na orientação Portrait:

Projeto Android em portrait e com o ConstraintLayout

E na orientação Landscape:

Projeto Android em landscape e com o ConstraintLayout

Note que em Landscape há um problema. O último TextView adicionado fica sobre o primeiro TextView incluído no layout.

Isso acontece, pois não há ligação entre esses TextView, digo, a ligação do topo do último TextView adicionado com o bottom do primeiro.

Logo realize as seguintes alterações no último TextView adicionado:

  • Side Handle: Ligue o lado esquerdo dele com o lado esquerdo do ConstraintLayout;
  • Side Handle: Ligue o bottom dele com o bottom do ConstraintLayout
  • Side Handle: Ligue o topo dele com o topo do TextView acima dele;
  • Em Properties clique nas linhas verticais e horizontais dentro do quadrado mais escuro até que elas fiquem com o tipo Wrap Content;
  • Ainda em Properties, para as margens bottom, left e top coloque respectivamente os valores: 16, 16 e 8.

Executando o projeto novamente e testando diretamente em Landscape temos:

Projeto Android em teste direto em landscape

Note que assim que foi adicionado um novo Side Handle do eixo x o Baseline Handle do último TextView foi automaticamente removido, isso acontece, pois, a princípio, não é possível ter um Side Handle do eixo x e o constraint Baseline Handle definidos pelo mesmo widget.

Note que também não é possível criar vínculos entre um Side Handle de um eixo de um widget com um Side Handle de outro eixo de um outro widget.

Alterando layout já existente

Caso queira atualizar um layout existente para se tornar um ConstraintLayout siga as instruções aqui.

Abaixo da aba de Views tem uma aba Component Tree. No layout root (caso seja esse que você queira alterar) clique com o botão direito do mouse e logo em seguida clique em Convert ScrollView to ConstraintLayout:

Opção Convert ScrollView to ConstraintLayout

A seguinte tela aparecerá:

Convertendo, de maneira automática, layout existente para um layout com ConstraintLayout

Onde a primeira opção indica que o layout será refatorado com o intuito de acabar com os layouts aninhados e constraints serão utilizadas no lugar dos aninhamentos.

A segunda opção informa que os layouts referenciados dentro do layout atual não serão refatorados.

Configuração de ConstraintLayout via Java API

Apesar de eu não recomendar, você pode aplicar as configurações de ConstraintLayout via Java API, veja o código abaixo da MainActivity:

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

ConstraintLayout constraintLayout = new ConstraintLayout(this);
constraintLayout.setId( R.id.constraintLayout );
ConstraintLayout.LayoutParams lpCl = new ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT );
constraintLayout.setLayoutParams( lpCl );

ImageView imageView = new ImageView(this);
imageView.setId( R.id.imageView );
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(R.drawable.singapore);
lpCl = new ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.WRAP_CONTENT, dpToPx(186) );
lpCl.topToTop = constraintLayout.getId();
lpCl.leftToLeft = constraintLayout.getId();
lpCl.rightToRight = constraintLayout.getId();
imageView.setLayoutParams(lpCl);
constraintLayout.addView(imageView);

TextView textView = new TextView(this);
textView.setText("...");
textView.setPadding( dpToPx(16), 0, 0, 0 );
lpCl = new ConstraintLayout.LayoutParams( dpToPx(126), ConstraintLayout.LayoutParams.WRAP_CONTENT );
lpCl.topToBottom = imageView.getId();
lpCl.leftToLeft = constraintLayout.getId();
lpCl.setMargins(0, dpToPx(8), 0, 0);
textView.setLayoutParams(lpCl);
constraintLayout.addView(textView);

setContentView(constraintLayout);
}

private int dpToPx(int dp){
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
}

Note que o código acima é apenas um trecho do código montado via UI Builder nesse artigo e no vídeo. Devido a qualidade do UI Builder recomendo a utilização dele para conseguir maior produção no desenvolvimento.

Note que foi necessário utilizar textView.setPadding(), pois o setMargins() do LayoutParams não funciona quando é em relação ao ConstraintLayout.

Abaixo um print do aplicativo rodando apenas com o código acima:

Testando o projeto de exemplo com definições de constraint direto na Java API

Com isso terminamos o projeto de teste com o ConstraintLayout.

Antes de prosseguir, não esqueça de se inscrever na 📫 lista de e-mails do Blog para receber semanalmente os conteúdos Android liberados aqui.

Se inscreva também no canal do Blog em YouTube Thiengo.

Vídeo com implementação passo a passo

Abaixo o vídeo com a implementação passo a passo do projeto desse artigo. Para acessar o código completo do projeto entre no GitHub dele: https://github.com/viniciusthiengo/constraint-layout.

Conclusão

Como já informado no início do artigo, o ConstraintLayout é uma excelente opção para aumento de performance na renderização dos layouts de seu aplicativo, provavelmente a melhor opção.

Isso porque esse layout é ainda mais flexível que o RelativeLayout permitindo que todas as Views fiquem bem alocadas em diferentes tipos de tela e também em diferentes orientações de tela.

Somente acompanhe o desenvolvimento desse layout caso for utilizá-lo em produção, pois ele, apesar de ter funcionado sem problemas nos testes aqui, ainda está em Alpha teste e sabemos que é possível ter vários problemas.

Curtiu o conteúdo? Não esqueça de compartilha-lo. E, por fim, de se inscrever na 📩 lista de e-mails, respondo às suas dúvidas também por lá.

Abraço.

Fontes

New Layout Editor with Constraint Layout

Using ConstraintLayout to design your views

Exploring the new Android ConstraintLayout

Android Studio 2.2 Preview - New UI Designer & Constraint Layout

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Notificação de Engajamento Pelo Firebase Console - Parte 12Notificação de Engajamento Pelo Firebase Console - Parte 12Android
Monetização sem Anúncios utilizando a Huq SDKMonetização sem Anúncios utilizando a Huq SDKAndroid
Use a Cabeça! Padrões de ProjetosUse a Cabeça! Padrões de ProjetosLivros
Refatoração de Código: Mover Embelezamento Para DecoratorRefatoração de Código: Mover Embelezamento Para DecoratorAndroid

Compartilhar

Comentários Facebook

Comentários Blog (13)

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...
Roberto castro (1) (0)
02/04/2018
E ai Thiego, tudo bem?

Thiego, pode me ajudar? Estou criando um app. gostaria de implementar * recupere sua senha na Tela de Login.

A conexão com Firebase estão funcionando...

Eu tenho as Views:
SplashAct;
LoginAct;
CadastroAct: e os  actLayouts. Tentei utilizar o código que vc explica do Nosso_Chate, e não consegui, da erro. Eu utilizo ConstraintLayout. Posso contar com a sua ajuda. Desde já lhe agradeço!
Responder
Vinícius Thiengo (0) (0)
03/04/2018
Roberto, tudo bem?

Qual a pilha de erro que está sendo apresentada para o algoritmo de recuperação de login do link a seguir?

https://www.thiengo.com.br/recuperacao-de-senha-firebase-atualizado-parte-8

Pois é exatamente nesta vídeo aula que eu já tinha atualizado o Firebase para uso da versão integrada ao Google.

Abraço.
Responder
Roberto Castro (0) (0)
04/04/2018
Obrigado Thiego, funcionou! vlw...
Responder
Victor (1) (0)
28/02/2017
Opa Thiengo, beleza?

Então, minha duvida é a seguinte: Estou criando um app pra aprender todas os temas que voce coloca no seu site, e com este post me questionei se com o ConstraintLayout eu devo deixar de utilizar os outros tipos de layout e se sim, para cada tela que minha app tem, esta será um constraintLayout?
Responder
Vinícius Thiengo (0) (0)
04/03/2017
Victor, tudo bem aqui.

Não, com o ConstraintLayout você ainda precisará dos outros componentes. O ConstraintLayout será muito útil para casos onde você tem muitas Views e a utilização de outros componentes de visualização poderiam não conseguir coloca-las, por exemplo, todas no mesmo nível.

Isso, pois aninhamento de Views é algo pesado para a renderização Android, utilizando alguns atributos como layout_weight, a coisa fica ainda pior.

Em alguns caos, alias, muitos casos, um RelativeLayout vai ser a opção suficiente. E agora com o FlexboxLayout temos um outro componente que alivia ainda mais o uso do ConstraintLayout.

Mais sobre o Flex em: https://github.com/google/flexbox-layout

Abraço.
Responder
04/03/2017
Perfeito! Muito boa a dica do Flex.
Muito Obrigado.
Responder
Ademilson (1) (0)
20/02/2017
Eu tenho uma dúvida, em relação ao ConstraintLayout. No meu layout eu adicionei TextInputLayout, porém ele não ocupa o tamanho todo, eu queria que ele ocupasse toda a largura do device, ou seja mathParent porém no ConstraintLayout não pode. Tem outra forma de eu fazer isto?
Responder
Vinícius Thiengo (0) (0)
24/02/2017
Ademilson, tudo bem?

É possível sim, faço isso no artigo / vídeo com o primeiro ImageView do layout.

Utilizando o Blue Print, ligue as bordas do TextInputLayout as bordas do layout. Na pior das hipóteses você terá de fazer direto no XML, caso tenha algum problema devido ao TextInputLayout ter um EditText dentro dele.

Já tentou assim? Abraço.
Responder
Ademilson (1) (0)
01/03/2017
E ai, estou fazendo assim, mas tenho que setar um atributo chamado ems=15 para ele aparecer. Meu medo, é estar deixando o campo do tamanho fixo.

A imagem deste link, demonstra exatamente como está:
http://stackoverflow.com/questions/38026578/layout-issue-with-textinputlayout-as-part-of-constraint-layout
Responder
Alex Passos (2) (0)
14/09/2016
Vinícius, você testou em android mais antigo como 3, 4?
Responder
Vinícius Thiengo (0) (0)
15/09/2016
Alex, blz?
Não testei. Encontrou mts bugs?
Responder
05/09/2016
Muito show seu post, mais uma novidade.
Responder
Vinícius Thiengo (2) (0)
05/09/2016
Vlw Jefferson, abraço.
Responder