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 t...
Um Problema Inicial
Um problema clássico de layout é o de um formulário arbitrário:
vários campos com tamanhos e proporçõe...
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 pe...
Um problema Inicial
Abordagem "newbie": ViewGroups aninhados

A primeira abordagem em que poderíamos pensar é aninhar ViewGroups básicos para ...
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 d...
Primeira tentativa de otimização
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.andr...
Primeira tentativa de otimização
??

Parece um pouco decepcionante,
não é exatamente o que vc
imaginou. Alguns componentes...
Lição 1: Conheça sua arma, antes de atirar.
A parte não óbvia por trás de qualquer ViewGroup, incluindo o RelativeLayout r...
Lição 2: Use apoios confiáveis.
Sabendo agora como realmente o RelativeLayout funciona, podemos assumir que a
estratégia d...
A primeira linha
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/produ...
A segunda linha
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/catego...
A terceira e quarta linhas
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="...
Resultado parcial
No fim, temos um resultado
quase sem defeitos.
Uma última coisa ainda
incômoda: as larguras dos botões
i...
Lição 3: Se as peças não se prendem muito bem, use cola!
<Button
android:layout_width="wrap_content"
android:layout_height...
Resultado final
Saldo final da modificação em
relação ao primeiro layout
aninhado: apenas uma view
comum extra em troca de...
Upcoming SlideShare
Loading in …5
×

RelativeLayout em 3 Lições

762 views

Published on

Muitos desenvolvedores iniciantes em Android sentem alguma dificuldade em trabalhar com ViewGroups mais complexos como o RelativeLayout.

Esse curto artigo e tutorial tem o objetivo de simplificar essa tarefa, com apenas três dicas muito simples de seguir.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
762
On SlideShare
0
From Embeds
0
Number of Embeds
28
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

RelativeLayout em 3 Lições

  1. 1. Relative Layout em 3 Lições Copérnico Vespúcio http://renascienza.wix.com
  2. 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. 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. 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.
  5. 5. Um problema Inicial
  6. 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. 7. Abordagem "newbie": ViewGroups aninhados 5 ViewGroups são usados apenas para dispôr os componentes!
  8. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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!

×