Escolar Documentos
Profissional Documentos
Cultura Documentos
WM21 Android Layouts
WM21 Android Layouts
Android
possvel hoje em dia construirmos GUIs to complexas quanto os requisitos exigidos pelo
mundo real.
E quando o contexto mobilidade, o desenvolvimento da mesma no pode ser
adotado como para Desktops ou Web, haja vista as restries de recursos grficos
inerentes aos dispositivos mveis. Porm, esta realidade est mudando. Idealizadores de
plataformas mveis vm estudando novas formas de construo de interfaces grficas
para permitir mais flexibilidade e riqueza no desenvolvimento de aplicaes mveis. E
uma delas Android, por meio de seus layouts que so totalmente definidos em XML.
Neste artigo, voc aprender como construir layouts complexos em Android.
Primeiramente, ser descrito como a plataforma implementa a hierarquia de componentes
de tela. Depois, sero explicadas as caractersticas dos principais layouts, que so:
LinearLayout, FrameLayout, AbsoluteLayout, RelativeLayout e TableLayout. Finalmente,
ser mostrado como se criar layouts complexos e como estend-los para que estruturas
grficas mais complexas possam ser desenvolvidas, sendo para isso utilizado uma
aplicao que simula a previso do tempo para cidades do Brasil.
LinearLayout
Este layout (criado por padro no arquivo main.xml quando construmos um
projeto) utilizado para dispor seus componentes em uma nica direo (por meio do
atributo android:layout_orientation): vertical ou horizontal (Figura 3). Sendo assim, sua
aplicao conter somente uma lista de componentes caso estes sejam dispostos na vertical
(Figura 4), passando o valor vertical para o atributo android:orientation de
<LinearLayout>, ou uma nica linha de componentes localizada na parte de cima do
layout caso estes sejam dispostos na horizontal (Figura 5), atribuindo a este atributo o
valor horizontal. Este layout respeita as margens entre os seus filhos e alinhamento (ao
centro, esquerda ou direita. Em Android, chamamos este atributo de gravity).
possvel tambm atribuir, individualmente, pesos (Figura 6) para os componentes
para que estes possam ocupar o restante do espao do layout, evitando que pequenos
objetos deixem espao desnecessrio no layout. Por padro, todos os componentes
adicionados possuem peso igual a 0. Porm, caso mais de um objeto utilize peso (Figura
7), ento os componentes sero ajustados para preencherem igualmente o espao de seu
pai. Para ver isto na prtica, basta voc adicionar o atributo android:layout_weight=1
Listagem 1. Linearlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="fill_parent">
<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Texto1" />
<EditText android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Texto2" />
</LinearLayout>
FrameLayout
O FrameLayout arranja seus filhos de acordo com uma pilha de componentes que
so adicionados, sendo que o topo da pilha contm o objeto que foi adicionado por ltimo,
como podemos perceber na pilha ao lado de FrameLayout (Figura 8), em que o primeiro
componente na pilha um View de cor azul e o do topo, de cor roxa. Podemos utiliz-lo
quando, por exemplo, queremos usar vrias imagens, onde uma trocada (sobreposta)
pela outra (como um slide de imagens) conforme vo sendo adicionadas.
O tamanho total de um FrameLayout definido pelo seu maior filho mais o
espaamento (padding) e todos os componentes so agrupados no canto superior
esquerdo do layout. Porm, a sua utilizao comumente d-se a partir de suas subclasses,
como ImageSwitcher, ViewAnimator, ViewSwitcher, ScrollView, TabHost, etc (para
maiores
detalhes
confira
a
referncia
desta
classe
em
http://code.google.com/android/reference/android/widget/FrameLayout.html).
A
Listagem 2 mostra como este layout implementado em XML e a Figura 9, exibe como ele
visualizado na tela do emulador.
Listagem 2. framelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText android:layout_width="120px"
android:layout_height="wrap_content" android:text="Texto1"
android:layout_weight="1" />
<EditText android:layout_width="90px"
android:layout_height="wrap_content" android:text="Texto2"
android:layout_weight="1" />
<EditText android:layout_width="60px"
android:layout_height="wrap_content" android:text="Texto3" />
</FrameLayout>
AbsoluteLayout
Este tipo de layout organiza seus componentes de forma a implementar um plano
cartesiano, no qual as suas posies x e y devem ser definidas para que estes possam ser
posicionados de forma absoluta (Figura 10), sendo que os valores da coordenada x
crescem da esquerda para a direita e da coordenada y, de cima para baixo. Caso os
componentes no declarem as suas posies explicitamente, eles sero dispostos na
posio (0,0). Este layout deve ser utilizado com cautela, pois, alm dos objetos serem
sobrepostos (como podemos ver os Views na posio (x4,y4) e (x7,y7)) caso as suas
posies sejam informadas incorretamente, o layout da sua aplicao pode no se
comportar como esperado caso ela seja desenvolvida para rodar em dispositivos com
resolues de telas diferentes (Figura 11 e Figura 12).
Para simularmos este efeito, mudaremos o skin do emulador, que por padro o
HVGA-P 320x420 em formato retrato (vermelho), para o skin Q-VGA 240x320 em formato
retrato (branco). Para isso, clicamos com boto direito do mouse em cima do projeto e
vamos em Open Run Dialog....Depois, do lado direito, clicamos na aba Target e em Screen
Size selecionamos QVGA-P. Rodamos a aplicao e podemos agora ver, que alguns
componentes so posicionados quase fora da tela do dispositivo. A Listagem 3 exibe o
layout em XML que foi utilizado nas figuras anteriores.
Figura 12. Problema que pode ocorrer em dispositivos com resolues de tela diferente.
Listagem 3. absolutelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="fill_parent">
<EditText android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Texto1"
android:layout_x="45px"
android:layout_y="87px" />
<EditText android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Texto2"
android:layout_x="90px"
android:layout_y="12px" />
<EditText android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Texto 3"
android:layout_x="90px"
android:layout_y="250px" />
</AbsoluteLayout>
RelativeLayout
Neste layout, os componentes so ajustados atravs de relacionamentos entre si ou
ao seu pai. A Figura 13 exibe quatro componentes: um TextView, um EditText e dois
Buttons. Perceba que o EditText com id textEntry possui um atributo below, informando
que o mesmo deve ser posicionado embaixo do TextView label1. O mesmo ocorre com o
Button okButton, onde este ajustado em baixo do EditText textEntry e tambm
alinhado direita referente ao seu pai. Um detalhe importante: caso um componente
referencie (por meio da propriedade below, por exemplo) algum outro componente, este
primeiro deve obrigatoriamente ser definido antes (definindo um nome no atributo
android:id), caso contrrio ocorrer um erro em sua estrutura de layout. Porm, nem todos
componentes precisam definir um id (como podemos ver o Button Cancel), sendo isso
10
somente necessrio se em algum local de seu layout este componente ser referenciado. A
Listagem 4 mostra um exemplo de tela de autenticao que utiliza RelativeLayout.
Listagem 4. relativelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="fill_parent">
<TextView android:id="@+id/tvLogin"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="Usurio:" />
<EditText android:id="@+id/etLogin"
android:layout_width="250px" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="usuario"
android:layout_below="@id/tvLogin" />
<TextView android:id="@+id/tvSenha"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="Senha:"
android:layout_below="@id/etLogin" />
11
<EditText android:id="@+id/etSenha"
android:layout_width="250px" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:text="Texto2"
android:password="true" android:layout_below="@id/tvSenha" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Logar"
android:layout_centerHorizontal="true"
android:layout_below="@+id/etSenha" />
</RelativeLayout>
TableLayout
O TableLayout comporta seus filhos em linhas e colunas. Cada filho representado
pelo componente TableRow (que tambm uma espcie de LinearLayout restrito na
direo horizontal) que permite que uma ou mais clulas sejam adicionados
horizontalmente, sendo que cada clula pode conter somente um nico View (Figura 15).
O nmero de colunas definido pela linha que tiver mais clulas. Este layout no
mostra as linhas utilizadas para dividir TableRows, colunas ou clulas (mostradas em
linhas tracejadas vermelhas). Conforme uma TableRow for sendo adicionado, o prximo
ser adicionado abaixo da anterior e assim sucessivamente. As clulas podem ser vazias e
as colunas podem ser ocultadas, podem ser marcadas para preencherem o espao restante
da tela ou para que sejam compressveis para forar que estas sejam ajustadas at que
completem o espao restante da tela. Caso o atributo android:layout_width e
android:layout_height no sejam declarados, este layout ir forar para que a largura de
cada componente seja automaticamente FILL_PARENT e a altura WRAP_CONTENT. A
Listagem 5 exibe o arquivo XML definido para TableLayout e a Figura 16 exibe este layout
no emulador.
Figura 15. Representao de tabela como layout para componentes com TableLayout.
12
Listagem 5. tablelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="fill_parent">
<TableRow>
<TextView android:text="Nome:" />
<EditText android:text="Ramon Rabello" />
</TableRow>
<TableRow>
<TextView android:text="Data Nasc.:" />
<EditText android:text="21/03/1986" />
</TableRow>
<TableRow>
<Button android:text="Cadastrar" />
</TableRow>
</TableLayout>
13
Listagem 6. complexlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow>
<AbsoluteLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="View"
android:layout_x="10px" android:layout_y="123px" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="View"
android:layout_x="10px" android:layout_y="12px" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="View"
android:layout_x="66px" android:layout_y="67px" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="View"
14
android:layout_x="120px" android:layout_y="12px" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="View"
android:layout_x="120px" android:layout_y="123px">
</Button>
</AbsoluteLayout>
<LinearLayout android:orientation="vertical">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
</LinearLayout>
</TableRow>
</TableLayout>
android:text="View" />
android:text="View" />
android:text="View" />
android:text="View" />
Estendendo layouts
Android no possui somente os componentes de layouts que foram explicados em
sees anteriores. Eles so os principais e a plataforma ainda disponibiliza uma gama de
layouts que utilizaram como base estes. A Tabela 1 mostra alguns exemplos destes
layouts.
Porm, caso nenhum destes se enquadrem nas especificaes grficas da sua
aplicao, a plataforma possui um framework que permite que layouts sejam estendidos
para suprir as necessidades do seu projeto.
Para exemplificarmos, criaremos uma aplicao simples que permite simular
(utilizando mocks) a previso do tempo das cidades do Brasil. Para isso, ser utilizada
uma lista que, em vez de ser representada por um simples ListView (que o componente
que visualiza uma listagem de Views - por padro, este componente exibe TextViews em
sua listagem), conter elementos que representam um layout, que mostrar o nome da
cidade, a temperatura e uma imagem representando o status do clima. Achou
interessante? Ento vamos prtica! Criaremos um novo projeto e definiremos as nossas
classes que sero utilizadas no novo layout. A seguir sero descritas cada classe.
Primeiramente, definiremos uma Enumeration (Listagem 7) que representar os
possveis status do clima: que no nosso exemplo ser somente chuvoso, ensolarado ou
nublado. Depois definimos uma classe (Listagem 8) que ser o bean (modelo) responsvel
pela representao dos dados climticos. Foi criado tambm o mtodo utilitrio
getStatusClimaResource(), que ser utilizado para referenciar as imagens (que esto no
diretrio res/drawable/) de acordo com a classe R.java, os quais representaro os status
do clima, sendo carregada uma imagem padro j disponvel na plataforma
(android.R.drawable.unknown_image) caso nenhuma imagem possa ser carregada.
Seguindo, criamos outra classe, ClimaAdapterView, (Listagem 9) que ir estender
LinearLayout. Tivemos que estend-la, pois em Android no existe (ainda) um
componente que exiba, em uma nica linha da lista, tanto textos como imagens.
Ento, definimos o construtor desta classe passando como parmetro um Context
(Interface que permite funionalidades de um ambiente de aplicao, como carregamento
de Activities, disparo de Intents, etc), que ser a nossa ListActivity (subclasse indireta de
Context) que ser explicada futuramente (Listagem 11). Outro parmetro uma referncia
para o bean Clima que contm os dados climticos encapsulados.
Chamamos o construtor de LinearLayout (super(context)) e passamos o context.
Agora, ajustamos a direo deste layout para horizontal, por meio do mtodo
setOrientation() (equivalente ao atributo android:layout_orientation) e configuramos os
15
16
Descrio
Gallery
GridView
ListView
ScrollView
Spinner
SurfaceView
TabHost
ViewFlipper
ViewSwitcher
Listagem 7. StatusClima.java
package android.clima.adapter;
public enum StatusClima {
DESCONHECIDO, ENSOLARADO, NUBLADO, CHUVOSO
}
Listagem 8. Clima.java
package android.clima.adapter;
public class Clima {
public String cidade;
private int temperatura;
private StatusClima statusClima = StatusClima.DESCONHECIDO;
/* construtor e gets/sets */
public int getStatusClimaResource() {
switch (statusClima) {
case ENSOLARADO:
return R.drawable.ensolarado;
case NUBLADO:
return R.drawable.nublado;
case CHUVOSO:
return R.drawable.chuvoso;
}
return android.R.drawable.unknown_image;
}
}
Listagem 9. ClimaAdapterView.java
17
package android.clima.adapter;
/* imports */
public class ClimaAdapterView extends LinearLayout {
public ClimaAdapterView(Context context, Clima clima) {
super(context);
this.setOrientation(HORIZONTAL);
LinearLayout.LayoutParams cidadeParams =
new LinearLayout.LayoutParams(100, LayoutParams.WRAP_CONTENT);
cidadeParams.setMargins(1, 1, 1, 1);
TextView tvCidade = new TextView(context);
tvCidade.setText(clima.getCidade());
tvCidade.setTextSize(14f);
tvCidade.setTextColor(Color.WHITE);
tvCidade.setTypeface(Typeface.DEFAULT_BOLD);
addView(tvCidade, cidadeParams);
LinearLayout.LayoutParams temperaturaParams =
new LinearLayout.LayoutParams(40, LayoutParams.WRAP_CONTENT);
temperaturaParams.setMargins(2, 2, 2, 2);
TextView tvTemperatura = new TextView(context);
tvTemperatura.setText(Integer.toString(clima.getTemperatura())+"C");
tvTemperatura.setTextSize(14f);
tvTemperatura.setTypeface(Typeface.DEFAULT_BOLD);
tvTemperatura.setTextColor(Color.WHITE);
addView(tvTemperatura, temperaturaParams);
LinearLayout.LayoutParams statusClimaParams =
new LinearLayout.LayoutParams(25, LayoutParams.WRAP_CONTENT);
ImageView ivStatusClima = new ImageView(context);
ivStatusClima.setImageResource(clima.getStatusClimaResource());
addView(ivStatusClima, statusClimaParams);
}
}
18
climas.add(w);
w = new Clima("Recife", 18, StatusClima.CHUVOSO);
climas.add(w);
w = new Clima("Rio de Janeiro", 22, StatusClima.ENSOLARADO);
climas.add(w);
ClimaAdapter climaAdapter = new ClimaAdapter(this,climas);
setListAdapter(climaAdapter);
}
}
Concluses
Conseguimos perceber ao longo deste artigo como Android facilita o
desenvolvimento de interface grfica com usurio, permitindo que qualquer GUI seja
definida em um ou mais arquivos XML, o que diminui o nvel de acoplamento entre GUI e
outras partes do seu cdigo (as suas regras de negcio, por exemplo). Contudo, como
19