SlideShare uma empresa Scribd logo
1 de 18
Relative Layout em 3 Lições
Copérnico Vespúcio

http://renascienza.wix.com
Introdução
Desde que computadores ganharam telas e programas interfaces gráficas, dar suporte
a tamanhos e resoluções de tela diferentes é um desafio recorrente. No mundo móvel,
com sua infinidade de modelos que variam de acordo com o sempre flutuante gosto
dos consumidores, o tema é ainda mais relevante.
Algumas plataformas simplesmente subvalorizaram o problema e oferecem soluções
ineficientes, outras deixam o problema no colo dos desenvolvedores. Para a sorte de
quem desenvolve para o sistema operacional Android, ela não é uma dessas
plataformas. Usada atualmente em mais de 500 modelos diferentes em todo o mundo,
ela nasceu com a compatibilidade como compromisso.
Neste artigo, eu vou mostrar a melhor e mais simples estratégia para usar uma das
mais poderosas ferramentas de layout que o desenvolvedor Android tem a sua
disposição: O RelativeLayout.
Um Problema Inicial
Um problema clássico de layout é o de um formulário arbitrário:
vários campos com tamanhos e proporções diferentes. O designer
deve levar em consideração não apenas a extensão e a disposição
de cada campo, como também a maneira como eles
redimensionam quando a tela muda de tamanho.
Sua primeira tentação é organizar os campos por tamanho de forma
a seguir uma disposição mais ou menos regular? Bem, podem haver
ainda mais razões para não fazer isso:
Um Problema Inicial
a) A maior parte dos usuários no mundo lêem formulários da esquerda para a direita, na
ordem em que pensam nos dados. Trocar essa ordem lógica pode fazer com que fiquem
perdidos, aumentando o tempo que eles precisam para se acostumar à sua interface.
b) Por alguma razão, a maioria dos usuários fica mais confortável quando a maior parte da
informação em uma tela fica do lado direito. Se vc tem um componente que atraia mais o
olhar, como uma foto, posicioná-la do lado direito cria uma tela mais agradável.
c) Pode ser que o seu aplicativo esteja reproduzindo uma tela de outro programa ou um
documento impresso com o qual o usuário já esteja acostumado.
Um problema Inicial
Abordagem "newbie": ViewGroups aninhados

A primeira abordagem em que poderíamos pensar é aninhar ViewGroups básicos para conseguir
esse efeito, como na listagem que produz a tela a seguir. Não perca muito tempo com ela, porque é
a pior abordagem que vc pode adotar. Ela desperdiça recursos preciosos do dispositivo, porque:
a) Cada nó em uma árvore de layout custa memória: views e view groups são objetos complexos. Do
total de views nesse layout, mais de um terço é usado apenas para arrumar os componentes.
b) Cada View a ser desenhada envolve um ciclo de pré-medição, layout, medição e desenho. Cada
fase desse ciclo em um ViewGroup chama recursivamente o ciclo de todas as views agregadas a
ele. Por isso, view groups aninhados tem péssima performance. E isso consome tempo e bateria.
Esse é o motivo da existência de abordagens como RelativeLayout . Com ele, vc pode criar qualquer
disposição que quiser, usando um único ViewGroup.
Abordagem "newbie": ViewGroups aninhados

5 ViewGroups são usados apenas
para dispôr os componentes!
Primeira tentativa de otimização
A ideia por trás do RelativeLayout é aparentemente muito simples. Direto das
páginas da documentação:
"A posição de cada view pode ser especificada como a relação entre as irmãs
(tais como para a esquerda, de ou abaixo de outra view) ou em posições
relativas ao container pai"
Então cada componente é fixado a partir da posição de pelo menos um outro.
Fácil. Ok, vamos fazer isso. A regra parece simples: vc vai adicionando os
componentes e amarrando os próximos no predecessor mais adequado.
Primeira tentativa de otimização
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="450dp"
android:background="#E0E0E0E0"
tools:context=".MainActivity">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/product"
android:hint="Product"

android:layout_below="@+id/product"
android:layout_alignParentRight="true"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/price"
android:hint="USD 0.00"

/>
<EditText
android:layout_width="64dp"
android:layout_height="wrap_content"
android:id="@+id/ref"
android:hint="REF"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/product"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/retailer"
android:hint="Ret. Code"
android:layout_toRightOf="@+id/ref"
/>

android:layout_below="@+id/product"
android:layout_toRightOf="@+id/category"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/taxes"
android:hint="0%"
android:layout_below="@+id/product"
android:layout_toRightOf="@+id/price"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/amount"
android:hint="0"

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/category"
android:hint="Category"
android:layout_below="@+id/product"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/photo"

<ImageView
android:layout_width="160dp"
android:layout_height="256dp"
android:id="@+id/photo"
android:src="@drawable/person"

android:layout_below="@+id/product"
android:layout_toRightOf="@+id/taxes"
android:layout_toLeftOf="@+id/photo" />
/>

<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/description"
android:hint="Description"
android:layout_below="@+id/category"
android:layout_toLeftOf="@+id/photo"
android:layout_alignParentLeft="true"

/>

<EditText
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/comments"
android:hint="Comments"
android:gravity="top"
android:inputType="textMultiLine"
android:layout_below="@+id/description"
android:layout_toLeftOf="@+id/photo"

/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Validate"
android:id="@+id/validate"
android:layout_below="@+id/comments"

/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/send"
android:layout_below="@+id/comments"
android:layout_toRightOf="@+id/validate"
</RelativeLayout>

/>
Primeira tentativa de otimização
??

Parece um pouco decepcionante,
não é exatamente o que vc
imaginou. Alguns componentes
estão ocultos, outros mal
dimensionados e, caso vc precise
mudar a posição de um
componente chave, o resto da sua
UI vai cair como um castelo de
cartas!
Esse é o ponto em que a maioria
desiste após algumas tentativas e
faz uma regressão para o layout
aninhado anterior.

Não vamos fazer isso. Somos corajosos. Somos ninjas!
Vamos às nossas 3 lições:
Lição 1: Conheça sua arma, antes de atirar.
A parte não óbvia por trás de qualquer ViewGroup, incluindo o RelativeLayout reside nas respostas de
duas perguntas:
a) Como ele posiciona os componentes?
Assumir que esse ViewGroup posiciona cada componente em relação a outros ou ao container-pai é
correto, mas limitado. Vc precisa lembrar que uma tela tem um eixo cartesiano com uma coordenada
horizontal (x) e vertical (y). Sendo assim, para ancorar direito a posição de um componente, vc precisa
de ambas as coordenadas.
No Relative Layout, sempre ancore um componente tanto na vertical quanto na horizontal
Importante: Não são permitidas "referências cruzadas", ou seja: se o componente A usa o componente
B como apoio, o componente B não pode usar o componente A como apoio.
b) Como ele dimensiona os componentes?
Os mais atentos perceberão que RelativeLayout possui constraints de alinhamento (borda superior,
borda inferior, esquerda e direita) que podem posicionar suas bordas em relação às bordas de outros
componentes ou do container-pai. A posição dessas bordas determina o tamanho do componente na
tela e sobrescreve qualquer medida especificada.
No entanto, quando há ausência de constraints que determinem a largura e/ou a altura do componente,
a medida especificada é utilizada.
Lição 2: Use apoios confiáveis.
Sabendo agora como realmente o RelativeLayout funciona, podemos assumir que a
estratégia de fazer os componentes de uma tela dependerem inteiramente uns dos
outros faz tanto sentido quanto a de amigos bêbados saindo de uma festa tentanto se
apoiar uns nos outros.
Ao invés disso, use os pontos de referência mais confiáveis: os do container-pai. Você
tem a sua disposição quatro bordas e o centro. O container-pai nunca muda na
manutenção - porque vc não precisa especificar um id para usá-lo - e é esperado que
ele sempre tenha as proporções corretas em relação a tela em que está inserido.
Em primeiro lugar, sempre que houver escolha entre usar um outro componente ou o
container para posição ou alinhamento, escolha o container.
Em segundo lugar, sempre que houver opção para usar um componente de tamanho
e/ou posição fixos como referência, prefira essa opção.
Vejamos como fica isso, na prática, reescrevendo nosso exemplo
A primeira linha
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/product"
android:hint="Product"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/ref"
android:minWidth="180dp"/>

Alinhamos todos os componentes no topo do
container. O primeiro componente da linha é
ancorado na borda esquerda e o último na borda
direita. Isso dá a ancoragem sólida que já discutimos.

<EditText
android:layout_width="64dp"
android:layout_height="wrap_content"
android:id="@+id/ref"
android:hint="REF"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/retailer"
/>

Vimos em nosso rascunho que na primeira linha a
caixa "Product" é a única com permissão de
redimensionar na largura. Para conseguir isso
fixamos o tamanho dos dois outros componentes da
linha e deixamos o tamanho de "Product" para variar
dentro de um limite mínimo especificado até o
máximo permitido.

<EditText
android:layout_width="180dp"
android:layout_height="wrap_content"
android:id="@+id/retailer"
android:hint="Ret. Code"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
/>

Os tamanhos fixos funcionam porque, na ausência de
outros fatores, a medida especificada é respeitada.
Uma vez em que são os componentes da direita a
terem tamanhos fixos, posicionamos a borda de
"Product" a eles e não o contrário.
A segunda linha
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/category"
android:hint="Category"
android:layout_below="@+id/product"
android:layout_alignParentLeft="true"
android:minWidth="200dp"
/>

Olhando em nosso rascunho, vimos que o único componente da linha
que pode variar de tamanho é "Photo".

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/photo"
android:src="@drawable/person"
android:layout_alignParentRight="true"
android:layout_below="@+id/ref"
android:maxWidth="250dp"
android:maxHeight="250dp"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:minHeight="180dp"
android:minWidth="180dp" />

No entanto o bom senso nos diz que os outros componentes na linha
precisam ter tamanhos mínimos e que o campo "Photo" deveria ter
limites máximos (do contrário escolher uma foto especialmente grande
engoliria o resto da tela).

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/price"
android:hint="USD 0.00"
android:layout_below="@+id/product"
android:layout_toRightOf="@+id/category"
android:layout_toLeftOf="@+id/taxes"
android:minWidth="100dp"
/>
<EditText
android:layout_width="48dp"
android:layout_height="wrap_content"
android:id="@+id/taxes"
android:hint="0%"
android:layout_below="@+id/product"
android:layout_toLeftOf="@+id/photo"
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/amount"
android:hint="0"
android:layout_below="@+id/product"
android:layout_toRightOf="@+id/taxes"
android:layout_toLeftOf="@+id/photo"
android:minWidth="96dp"
/>

/>

Para isso usamos maxWidth, maxHeight e minWidth, minHeight onde
necessário.
Importante: ImageView é um componente um tanto particular. Quando
há conteúdo, define seu tamanho de acordo com este e não com as
medidas especificadas (layout_width, layout_height, maxWidth,
maxHeight, minWidth, minHeight). Para mudar esse comportamento
definimos "android:adjustViewBounds" como "true" e especificamos um
método de redimensionamento do conteúdo.
Uma vez que agora é a direita da linha a parte com a largura variável,
ancoramos os componentes à direita com os da esquerda.
A terceira e quarta linhas
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/description"
android:hint="Description"
android:layout_below="@+id/category"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/taxes"
android:layout_alignEnd="@+id/taxes"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/comments"
android:hint="Comments"
android:gravity="top"
android:inputType="textMultiLine"
android:layout_alignBottom="@+id/photo"
android:layout_below="@+id/description"
android:layout_alignParentLeft="true"
android:layout_toRightOf="@id/photo"
android:layout_alignRight="@+id/taxes"
android:layout_alignEnd="@+id/taxes"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Validate"
android:id="@+id/validate"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignRight="@+id/taxes"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/send"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="@+id/amount"/>

O mesmo é feito com as linhas de "Description"
e "Comments".
Alinhamos a borda inferior de "Comments" com
a borda inferior de "Photo", de forma coerente.
Finalmente, alinhamos os botões da parte
inferior com o container.
Poderíamos alinhar as bordas inferiores de
"Comments" e "Photo" com o topo dos botões,
mas não queremos deformar "Photo" caso a
altura do container fique maior do que
gostaríamos.
Resultado parcial
No fim, temos um resultado
quase sem defeitos.
Uma última coisa ainda
incômoda: as larguras dos botões
inferiores não são proporcionais
entre si.
Isso acontece porque estão
baseadas em referências acima e
não podemos basear um botão no
outro porque nenhum deles tem
largura fixa (eis a regra de que
dois bêbados não podem se
apoiar um no outro)...
O que fazer?
Lição 3: Se as peças não se prendem muito bem, use cola!
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Validate"
android:id="@+id/validate"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/glue"/>
<View
android:layout_width="8dp"
android:layout_height="48dp"
android:id="@+id/glue"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/send"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_toRightOf="@+id/glue"/>

O problema dos botões na parte de baixo é que
eles precisam de algo em que se apoiar, um
terceiro elemento. Eu o chamo de "componente
cola".
Adicionamos uma view extra e a ancoramos
com a parte inferior do container e com o seu
centro horizontal. Agora os botões possuem
um ponto fixo no qual se ancorar!
Resultado final
Saldo final da modificação em
relação ao primeiro layout
aninhado: apenas uma view
comum extra em troca de 5
ViewGroups.
Conclusão: O ViewGroup
RelativeLayout, usado
corretamente, é o um dos mais
poderosos e versáteis recursos
que o design de interface pode
lançar mão. Agora, um pouco de
prática é tudo o que você precisa
para se tornar um mestre, como
em tudo o mais.
Boa jornada!

Mais conteúdo relacionado

Semelhante a RelativeLayout em 3 Lições

Como criar interfaces gráficas com android
Como criar interfaces gráficas com androidComo criar interfaces gráficas com android
Como criar interfaces gráficas com androidRicardo Ogliari
 
Layout complexos
Layout complexosLayout complexos
Layout complexosallefbarros
 
Desenvolvimento de Apps e Games para Android - Parte 2
Desenvolvimento de Apps e Games para Android - Parte 2Desenvolvimento de Apps e Games para Android - Parte 2
Desenvolvimento de Apps e Games para Android - Parte 2Erisvaldo Junior
 
Programando Android - Aula 3
Programando Android - Aula 3Programando Android - Aula 3
Programando Android - Aula 3Kalil Maciel
 
Aula - Gerenciadores de layout
Aula - Gerenciadores de layoutAula - Gerenciadores de layout
Aula - Gerenciadores de layoutJanynne Gomes
 
Introdução as práticas de desenvolvimento web com design responsivo
Introdução as práticas de desenvolvimento web com design responsivoIntrodução as práticas de desenvolvimento web com design responsivo
Introdução as práticas de desenvolvimento web com design responsivoRégis Eduardo Weizenmann Gregol
 
Web Design Responsivo
Web Design ResponsivoWeb Design Responsivo
Web Design ResponsivoVictor Melo
 
Os cuidados e os limites do Responsive Web Design
Os cuidados e os limites do Responsive Web DesignOs cuidados e os limites do Responsive Web Design
Os cuidados e os limites do Responsive Web DesignDiego Eis
 
Computação Móvel 2012.2 - Android
Computação Móvel 2012.2 - AndroidComputação Móvel 2012.2 - Android
Computação Móvel 2012.2 - AndroidTiago Bencardino
 
Layouts e multiplas activities
Layouts e multiplas activitiesLayouts e multiplas activities
Layouts e multiplas activitiesCalebeMiquissene
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Nelson Glauber Leal
 
Curso Maquete eletrônica Aula1
Curso Maquete eletrônica Aula1Curso Maquete eletrônica Aula1
Curso Maquete eletrônica Aula1Cleber Gouveia
 
Android Core Aula 6 - Desenvolvimento de aplicações Android
Android Core Aula 6 -  Desenvolvimento de aplicações AndroidAndroid Core Aula 6 -  Desenvolvimento de aplicações Android
Android Core Aula 6 - Desenvolvimento de aplicações AndroidFelipe Silveira
 
Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3Erisvaldo Junior
 
Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)marcondes da luz barros
 
Aplicações java com netbeans
Aplicações  java com  netbeansAplicações  java com  netbeans
Aplicações java com netbeansThalles Anderson
 

Semelhante a RelativeLayout em 3 Lições (20)

Como criar interfaces gráficas com android
Como criar interfaces gráficas com androidComo criar interfaces gráficas com android
Como criar interfaces gráficas com android
 
Layout complexos
Layout complexosLayout complexos
Layout complexos
 
Desenvolvimento de Apps e Games para Android - Parte 2
Desenvolvimento de Apps e Games para Android - Parte 2Desenvolvimento de Apps e Games para Android - Parte 2
Desenvolvimento de Apps e Games para Android - Parte 2
 
Aplicacoes responsivas
Aplicacoes responsivasAplicacoes responsivas
Aplicacoes responsivas
 
Responsive wordpress
Responsive wordpressResponsive wordpress
Responsive wordpress
 
Programando Android - Aula 3
Programando Android - Aula 3Programando Android - Aula 3
Programando Android - Aula 3
 
Aula - Gerenciadores de layout
Aula - Gerenciadores de layoutAula - Gerenciadores de layout
Aula - Gerenciadores de layout
 
Introdução as práticas de desenvolvimento web com design responsivo
Introdução as práticas de desenvolvimento web com design responsivoIntrodução as práticas de desenvolvimento web com design responsivo
Introdução as práticas de desenvolvimento web com design responsivo
 
Prototipagem
PrototipagemPrototipagem
Prototipagem
 
Web Design Responsivo
Web Design ResponsivoWeb Design Responsivo
Web Design Responsivo
 
Os cuidados e os limites do Responsive Web Design
Os cuidados e os limites do Responsive Web DesignOs cuidados e os limites do Responsive Web Design
Os cuidados e os limites do Responsive Web Design
 
Computação Móvel 2012.2 - Android
Computação Móvel 2012.2 - AndroidComputação Móvel 2012.2 - Android
Computação Móvel 2012.2 - Android
 
Layouts e multiplas activities
Layouts e multiplas activitiesLayouts e multiplas activities
Layouts e multiplas activities
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023
 
Curso Maquete eletrônica Aula1
Curso Maquete eletrônica Aula1Curso Maquete eletrônica Aula1
Curso Maquete eletrônica Aula1
 
Android Core Aula 6 - Desenvolvimento de aplicações Android
Android Core Aula 6 -  Desenvolvimento de aplicações AndroidAndroid Core Aula 6 -  Desenvolvimento de aplicações Android
Android Core Aula 6 - Desenvolvimento de aplicações Android
 
Sap
SapSap
Sap
 
Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3Desenvolvimento de Apps e Games para Android - Parte 3
Desenvolvimento de Apps e Games para Android - Parte 3
 
Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)
 
Aplicações java com netbeans
Aplicações  java com  netbeansAplicações  java com  netbeans
Aplicações java com netbeans
 

RelativeLayout em 3 Lições

  • 1. Relative Layout em 3 Lições Copérnico Vespúcio http://renascienza.wix.com
  • 2. Introdução Desde que computadores ganharam telas e programas interfaces gráficas, dar suporte a tamanhos e resoluções de tela diferentes é um desafio recorrente. No mundo móvel, com sua infinidade de modelos que variam de acordo com o sempre flutuante gosto dos consumidores, o tema é ainda mais relevante. Algumas plataformas simplesmente subvalorizaram o problema e oferecem soluções ineficientes, outras deixam o problema no colo dos desenvolvedores. Para a sorte de quem desenvolve para o sistema operacional Android, ela não é uma dessas plataformas. Usada atualmente em mais de 500 modelos diferentes em todo o mundo, ela nasceu com a compatibilidade como compromisso. Neste artigo, eu vou mostrar a melhor e mais simples estratégia para usar uma das mais poderosas ferramentas de layout que o desenvolvedor Android tem a sua disposição: O RelativeLayout.
  • 3. Um Problema Inicial Um problema clássico de layout é o de um formulário arbitrário: vários campos com tamanhos e proporções diferentes. O designer deve levar em consideração não apenas a extensão e a disposição de cada campo, como também a maneira como eles redimensionam quando a tela muda de tamanho. Sua primeira tentação é organizar os campos por tamanho de forma a seguir uma disposição mais ou menos regular? Bem, podem haver ainda mais razões para não fazer isso:
  • 4. Um Problema Inicial a) A maior parte dos usuários no mundo lêem formulários da esquerda para a direita, na ordem em que pensam nos dados. Trocar essa ordem lógica pode fazer com que fiquem perdidos, aumentando o tempo que eles precisam para se acostumar à sua interface. b) Por alguma razão, a maioria dos usuários fica mais confortável quando a maior parte da informação em uma tela fica do lado direito. Se vc tem um componente que atraia mais o olhar, como uma foto, posicioná-la do lado direito cria uma tela mais agradável. c) Pode ser que o seu aplicativo esteja reproduzindo uma tela de outro programa ou um documento impresso com o qual o usuário já esteja acostumado.
  • 6. Abordagem "newbie": ViewGroups aninhados A primeira abordagem em que poderíamos pensar é aninhar ViewGroups básicos para conseguir esse efeito, como na listagem que produz a tela a seguir. Não perca muito tempo com ela, porque é a pior abordagem que vc pode adotar. Ela desperdiça recursos preciosos do dispositivo, porque: a) Cada nó em uma árvore de layout custa memória: views e view groups são objetos complexos. Do total de views nesse layout, mais de um terço é usado apenas para arrumar os componentes. b) Cada View a ser desenhada envolve um ciclo de pré-medição, layout, medição e desenho. Cada fase desse ciclo em um ViewGroup chama recursivamente o ciclo de todas as views agregadas a ele. Por isso, view groups aninhados tem péssima performance. E isso consome tempo e bateria. Esse é o motivo da existência de abordagens como RelativeLayout . Com ele, vc pode criar qualquer disposição que quiser, usando um único ViewGroup.
  • 7. Abordagem "newbie": ViewGroups aninhados 5 ViewGroups são usados apenas para dispôr os componentes!
  • 8. Primeira tentativa de otimização A ideia por trás do RelativeLayout é aparentemente muito simples. Direto das páginas da documentação: "A posição de cada view pode ser especificada como a relação entre as irmãs (tais como para a esquerda, de ou abaixo de outra view) ou em posições relativas ao container pai" Então cada componente é fixado a partir da posição de pelo menos um outro. Fácil. Ok, vamos fazer isso. A regra parece simples: vc vai adicionando os componentes e amarrando os próximos no predecessor mais adequado.
  • 9. Primeira tentativa de otimização <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="450dp" android:background="#E0E0E0E0" tools:context=".MainActivity"> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/product" android:hint="Product" android:layout_below="@+id/product" android:layout_alignParentRight="true" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/price" android:hint="USD 0.00" /> <EditText android:layout_width="64dp" android:layout_height="wrap_content" android:id="@+id/ref" android:hint="REF" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/product" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/retailer" android:hint="Ret. Code" android:layout_toRightOf="@+id/ref" /> android:layout_below="@+id/product" android:layout_toRightOf="@+id/category" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/taxes" android:hint="0%" android:layout_below="@+id/product" android:layout_toRightOf="@+id/price" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/amount" android:hint="0" <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/category" android:hint="Category" android:layout_below="@+id/product" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/photo" <ImageView android:layout_width="160dp" android:layout_height="256dp" android:id="@+id/photo" android:src="@drawable/person" android:layout_below="@+id/product" android:layout_toRightOf="@+id/taxes" android:layout_toLeftOf="@+id/photo" /> /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/description" android:hint="Description" android:layout_below="@+id/category" android:layout_toLeftOf="@+id/photo" android:layout_alignParentLeft="true" /> <EditText android:layout_width="match_parent" android:layout_height="200dp" android:id="@+id/comments" android:hint="Comments" android:gravity="top" android:inputType="textMultiLine" android:layout_below="@+id/description" android:layout_toLeftOf="@+id/photo" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Validate" android:id="@+id/validate" android:layout_below="@+id/comments" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" android:id="@+id/send" android:layout_below="@+id/comments" android:layout_toRightOf="@+id/validate" </RelativeLayout> />
  • 10. Primeira tentativa de otimização ?? Parece um pouco decepcionante, não é exatamente o que vc imaginou. Alguns componentes estão ocultos, outros mal dimensionados e, caso vc precise mudar a posição de um componente chave, o resto da sua UI vai cair como um castelo de cartas! Esse é o ponto em que a maioria desiste após algumas tentativas e faz uma regressão para o layout aninhado anterior. Não vamos fazer isso. Somos corajosos. Somos ninjas! Vamos às nossas 3 lições:
  • 11. Lição 1: Conheça sua arma, antes de atirar. A parte não óbvia por trás de qualquer ViewGroup, incluindo o RelativeLayout reside nas respostas de duas perguntas: a) Como ele posiciona os componentes? Assumir que esse ViewGroup posiciona cada componente em relação a outros ou ao container-pai é correto, mas limitado. Vc precisa lembrar que uma tela tem um eixo cartesiano com uma coordenada horizontal (x) e vertical (y). Sendo assim, para ancorar direito a posição de um componente, vc precisa de ambas as coordenadas. No Relative Layout, sempre ancore um componente tanto na vertical quanto na horizontal Importante: Não são permitidas "referências cruzadas", ou seja: se o componente A usa o componente B como apoio, o componente B não pode usar o componente A como apoio. b) Como ele dimensiona os componentes? Os mais atentos perceberão que RelativeLayout possui constraints de alinhamento (borda superior, borda inferior, esquerda e direita) que podem posicionar suas bordas em relação às bordas de outros componentes ou do container-pai. A posição dessas bordas determina o tamanho do componente na tela e sobrescreve qualquer medida especificada. No entanto, quando há ausência de constraints que determinem a largura e/ou a altura do componente, a medida especificada é utilizada.
  • 12. Lição 2: Use apoios confiáveis. Sabendo agora como realmente o RelativeLayout funciona, podemos assumir que a estratégia de fazer os componentes de uma tela dependerem inteiramente uns dos outros faz tanto sentido quanto a de amigos bêbados saindo de uma festa tentanto se apoiar uns nos outros. Ao invés disso, use os pontos de referência mais confiáveis: os do container-pai. Você tem a sua disposição quatro bordas e o centro. O container-pai nunca muda na manutenção - porque vc não precisa especificar um id para usá-lo - e é esperado que ele sempre tenha as proporções corretas em relação a tela em que está inserido. Em primeiro lugar, sempre que houver escolha entre usar um outro componente ou o container para posição ou alinhamento, escolha o container. Em segundo lugar, sempre que houver opção para usar um componente de tamanho e/ou posição fixos como referência, prefira essa opção. Vejamos como fica isso, na prática, reescrevendo nosso exemplo
  • 13. A primeira linha <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/product" android:hint="Product" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_toLeftOf="@id/ref" android:minWidth="180dp"/> Alinhamos todos os componentes no topo do container. O primeiro componente da linha é ancorado na borda esquerda e o último na borda direita. Isso dá a ancoragem sólida que já discutimos. <EditText android:layout_width="64dp" android:layout_height="wrap_content" android:id="@+id/ref" android:hint="REF" android:layout_alignParentTop="true" android:layout_toLeftOf="@id/retailer" /> Vimos em nosso rascunho que na primeira linha a caixa "Product" é a única com permissão de redimensionar na largura. Para conseguir isso fixamos o tamanho dos dois outros componentes da linha e deixamos o tamanho de "Product" para variar dentro de um limite mínimo especificado até o máximo permitido. <EditText android:layout_width="180dp" android:layout_height="wrap_content" android:id="@+id/retailer" android:hint="Ret. Code" android:layout_alignParentTop="true" android:layout_alignParentRight="true" /> Os tamanhos fixos funcionam porque, na ausência de outros fatores, a medida especificada é respeitada. Uma vez em que são os componentes da direita a terem tamanhos fixos, posicionamos a borda de "Product" a eles e não o contrário.
  • 14. A segunda linha <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/category" android:hint="Category" android:layout_below="@+id/product" android:layout_alignParentLeft="true" android:minWidth="200dp" /> Olhando em nosso rascunho, vimos que o único componente da linha que pode variar de tamanho é "Photo". <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/photo" android:src="@drawable/person" android:layout_alignParentRight="true" android:layout_below="@+id/ref" android:maxWidth="250dp" android:maxHeight="250dp" android:adjustViewBounds="true" android:scaleType="fitCenter" android:minHeight="180dp" android:minWidth="180dp" /> No entanto o bom senso nos diz que os outros componentes na linha precisam ter tamanhos mínimos e que o campo "Photo" deveria ter limites máximos (do contrário escolher uma foto especialmente grande engoliria o resto da tela). <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/price" android:hint="USD 0.00" android:layout_below="@+id/product" android:layout_toRightOf="@+id/category" android:layout_toLeftOf="@+id/taxes" android:minWidth="100dp" /> <EditText android:layout_width="48dp" android:layout_height="wrap_content" android:id="@+id/taxes" android:hint="0%" android:layout_below="@+id/product" android:layout_toLeftOf="@+id/photo" <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/amount" android:hint="0" android:layout_below="@+id/product" android:layout_toRightOf="@+id/taxes" android:layout_toLeftOf="@+id/photo" android:minWidth="96dp" /> /> Para isso usamos maxWidth, maxHeight e minWidth, minHeight onde necessário. Importante: ImageView é um componente um tanto particular. Quando há conteúdo, define seu tamanho de acordo com este e não com as medidas especificadas (layout_width, layout_height, maxWidth, maxHeight, minWidth, minHeight). Para mudar esse comportamento definimos "android:adjustViewBounds" como "true" e especificamos um método de redimensionamento do conteúdo. Uma vez que agora é a direita da linha a parte com a largura variável, ancoramos os componentes à direita com os da esquerda.
  • 15. A terceira e quarta linhas <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/description" android:hint="Description" android:layout_below="@+id/category" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignRight="@+id/taxes" android:layout_alignEnd="@+id/taxes"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/comments" android:hint="Comments" android:gravity="top" android:inputType="textMultiLine" android:layout_alignBottom="@+id/photo" android:layout_below="@+id/description" android:layout_alignParentLeft="true" android:layout_toRightOf="@id/photo" android:layout_alignRight="@+id/taxes" android:layout_alignEnd="@+id/taxes"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Validate" android:id="@+id/validate" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignRight="@+id/taxes"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" android:id="@+id/send" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_toRightOf="@+id/amount"/> O mesmo é feito com as linhas de "Description" e "Comments". Alinhamos a borda inferior de "Comments" com a borda inferior de "Photo", de forma coerente. Finalmente, alinhamos os botões da parte inferior com o container. Poderíamos alinhar as bordas inferiores de "Comments" e "Photo" com o topo dos botões, mas não queremos deformar "Photo" caso a altura do container fique maior do que gostaríamos.
  • 16. Resultado parcial No fim, temos um resultado quase sem defeitos. Uma última coisa ainda incômoda: as larguras dos botões inferiores não são proporcionais entre si. Isso acontece porque estão baseadas em referências acima e não podemos basear um botão no outro porque nenhum deles tem largura fixa (eis a regra de que dois bêbados não podem se apoiar um no outro)... O que fazer?
  • 17. Lição 3: Se as peças não se prendem muito bem, use cola! <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Validate" android:id="@+id/validate" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_toLeftOf="@+id/glue"/> <View android:layout_width="8dp" android:layout_height="48dp" android:id="@+id/glue" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send" android:id="@+id/send" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_toRightOf="@+id/glue"/> O problema dos botões na parte de baixo é que eles precisam de algo em que se apoiar, um terceiro elemento. Eu o chamo de "componente cola". Adicionamos uma view extra e a ancoramos com a parte inferior do container e com o seu centro horizontal. Agora os botões possuem um ponto fixo no qual se ancorar!
  • 18. Resultado final Saldo final da modificação em relação ao primeiro layout aninhado: apenas uma view comum extra em troca de 5 ViewGroups. Conclusão: O ViewGroup RelativeLayout, usado corretamente, é o um dos mais poderosos e versáteis recursos que o design de interface pode lançar mão. Agora, um pouco de prática é tudo o que você precisa para se tornar um mestre, como em tudo o mais. Boa jornada!