Você está na página 1de 19

1

Android

Construindo layouts complexos em Android

Ramon Ribeiro Rabello ramon.rabello@gmail.com graduado em Cincia da Computao pela Universidade da Amaznia (UNAMA). Trabalha com a tecnologia Java h 4 anos e j desenvolveu projetos utilizando as linguagens Delphi, C e C++. Possui experincia nas trs especificaes Java: JSE, JEE e JME.Trabalhou com desenvolvimento de aplicaes mveis comerciais (M-Commerce / M-Payment) e publicou artigos cientficos sobre aspectos referentes plataforma JME. Atualmente mestrando da Universidade Federal de Pernambuco (UFPE) na rea de Engenharia de Software.

De que se trata o artigo: Construo de layouts complexos em Android, principais layouts disponveis na plataforma, como aninh-los para permitir que estruturas grficas mais complexas sejam utilizadas e como estend-los para dar mais expressividade grfica s aplicaes mveis. Para que serve: Possibilitar a utilizao de layouts complexos em aplicaes mveis em Android, permitindo assim a melhoria da usabilidade e enriquecimento do mdulo de interface grfica dos projetos criados para a plataforma. Em que situao o tema til: Quando determinado requisito funcional grfico no puder ser satisfeito com a utilizao apenas de estruturas simples de layouts. A Interface Grfica com o Usurio (GUI) um dos aspectos essenciais em um Sistema de Informao, permitindo que o usurio final desfrute de forma fcil e muitas vezes intuitiva das funcionalidades fornecidas pelo software (graas aos seus widgets). Acompanhando sua evoluo por meio das Eras da Computao (desde que os comandos eram realizados em uma tela de texto), percebemos que as Linguagens de Programao de alto nvel tm enfatizado o seu uso e sua melhoria por meio de suas verses, sendo

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.

Hierarquia de Views e ViewGroups


Em Android, todos os componentes de interface grfica so representados por subclasses de android.view.View que representam os componentes grficos (os chamados widgets) como TextView, Button , TextEdit, RadioButton, Checkbox, etc; e a classe android.view.ViewGroup, que representa um container de Views e tambm ViewGroups. Ela a classe base para componentes de layouts, como LinearLayout, FrameLayout, AbsoluteLayout, RelativeLayout, TableLayout, etc. O fato de um ViewGroup tambm ser composto por um ou mais ViewGroups o fator que permite que layouts complexos (layouts aninhados) sejam desenvolvidos, como podemos observar na Figura 1.

Figura 1. Hierarquia de componentes de tela.

Respeitando os parmetros de layouts


Para que os componentes possam ser acomodados de acordo com o layout de seu pai, os mesmos devem manter uma relao de obedincia. Sendo assim, cada filho deve configurar os seus parmetros de layouts, por meio da classe ViewGroup.LayoutParams, que permite que estes determinem suas propriedades de posio e tamanho referente ao layout de seus pais. Portanto, todo layout deve possuir uma classe interna que obrigatoriamente estenda esta classe. Por exemplo, na Figura 2, podemos perceber que os filhos de LinearLayout (a

raiz da rvore) possuem os seus parmetros (LinearLayout.LayoutParams) para serem utilizados dentro de LinearLayout, como ocorre tambm para os filhos de RelativeLayout. Todo layout possui propriedades de largura e altura (atributos layout_width e layout_height, respectivamente), porm outros podem declarar aspectos de margens e bordas. possvel que estas propriedades sejam ajustadas manualmente (informando o valor exato), porm, desejvel que elas sejam configuradas possibilitando que o componente preencha o espao do seu pai ou se ajuste de acordo com o seu contedo (inserindo o valor fill_parent ou o valor wrao_content em android:layout_width ou android:layout_height, respectivamente). A seguir, sero descritos os principais layouts e suas caractersticas. Um aviso ao leitor: daqui por diante neste artigo, todos os layouts que sero explicados, sero definidos em arquivos XML separados (linearlayout.xml, framelayout.xml, etc). Dessa maneira, no preciso sobrescrever o layout anterior para ver como ele se comporta na tela do emulador, sendo somente necessrio alterar a referncia (R.layout.main) no mtodo setContentView(), de acordo com o layout a ser visualizado (R.layout.linearlayout, por exemplo). Isso nos permite construir vrios layouts para serem utilizados em nossos projetos Android.

Figura 2. Os componentes respeitando os parmetros de layouts dos seus pais.

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

para um ou mais Views e garantir que android:orientation de <LinearLayout> est com o valor vertical. A Listagem 1 mostra um exemplo de LinearLayout em XML.

Figura 3. Adicionando componentes em uma nica direo com LinearLayout.

Figura 4. Exemplificando LinearLayout na direo vertical.

Figura 5. Exemplificando LinearLayout na direo horizontal.

Figura 6. Atribuindo peso a um componente.

Figura 7. Atribuindo peso a mais de um componente.

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.

Figura 8. Criando uma pilha de componentes com FrameLayout.

Figura 9. Sobreposio de componentes com FrameLayout.

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 10. Utilizando o AbsoluteLayout.

Figura 11. Dispondo os componentes de forma absoluta com AbsoluteLayout.

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.

Figura 13. Utilizando componentes relativamente com RelativeLayout.

Figura 14. Ajustando os componentes relativamente com 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

Figura 16. Exemplo de TableLayout no emulador.

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>

Criando layouts complexos


Agora, reunindo tudo que foi aprendido at esta etapa, podemos construir aninhamentos de layouts para desenvolvermos nossas interfaces grficas mais ricas e complexas, como mostra a Figura 17, na qual mais externamente temos um TableLayout que possui um TableRow que possui dois filhos: do lado esquerdo um AbsoluteLayout e do outro lado, um LinearLayout com direo vertical, ambos comportando Views. Perceba que, mesmo com esse nvel de complexidade, todos os filhos (tantos os Views quanto os ViewGroups) se comportam especificamente de acordo com o layout pai graas s suas propriedades de parmetros de layout (definidas nas subclasses de ViewGroup.LayoutParams). s vezes, construir layouts pode se tornar uma atividade cansativa, haja vista o nmero de variveis que devero ser ajustadas manualmente no arquivo XML. Pensando nisso, foi desenvolvida uma ferramenta Open Source chamada DroidDraw que facilita o desenvolvimento no s destes layouts mas tambm dos widgets. Ela pode ser carregada tanto como um Applet ou em modo Standalone (executando um jar). Para baix-la e maiores informaes, acesse o link http://droiddraw.org. A Listagem 6 mostra como definimos esta estrutura no arquivo XML de layout e a Figura 18 mostra este layout no emulador.

13

Figura 17. Aninhando layouts para construir layouts complexos.

Figura 18. Reproduzindo layouts complexos.

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

parmetros de layout para cada objeto utilizando LinearLayout.LayoutParams, comeando primeiramente para a cidade (cidadeParams). Em LinearLayout.Params, passamos no seu construtor as informaes de largura (100) e altura (LayoutParams.WRAP_CONTENT) e depois, no mtodos setMargins() ajustamos as margens (todos com valor 1) da esqueda, de cima, da direita e de baixo deste objeto, respectivamente. Instanciamos o TextView tvCidade, passamos ao seu construtor um context, setamos seu texto utilizando o bean clima, o tamanho do texto (14f), a cor (Color.WHITE) e o tipo da fonte como negrito (Typeface.DEFAULT_BOLD). Adicionamos este TextView com os parmetros de layout ao nosso layout chamando o mtodo addView(). Configuramos depois os parmetros de layouts de tvTemperatura (temperaturaParams) e ivStatusClima (statusClimaParams), a seguir os adicionamos no nosso layout. Definimos agora a nossa classe ClimaAdapter (Listagem 10) que realizar, de fato, a listagem de objetos Climas. Se voc observar, ela estende BaseAdapter, que a classe base para objetos que queiram servir como ponte entre os dados e a interface grfica, que ser utilizada para visualiz-los de acordo com alguma fonte de dados (arrays, Cursors, etc). Ela utilizada por AdapterViews, que so Views cujo seus filhos so determinados por um Adapter, como o caso de ListView, que usa um ListAdaper. Resumindo: todo esse mecanismo o padro MVC (Modelo-Viso-Controle) por trs dos panos, que foi fortemente utilizado na plataforma Android para podermos realizar o binding de dados (modelo) com os Views (viso) utilizando Adapters (controle), diminuindo o grau de acoplamento entre ambos. Continuemos a anlise de nosso Adapter. Declaramos dois objetos: um Context representando nossa ListActivity e um List (climas) que conter objetos Climas que sero visualizados na lista. Como BaseAdapter abstrata, devemos implementar os mtodos abstratos (na verdade, estes mtodos pertencem interface Adapter) que so: getCount(), utilizado para retornar o nmero de objetos dentro da lista, que ser o tamanho de nossa List; getItem(), que retorna o item (Object) referente a uma posio na lista; getItemId() que retorna o id do item de acordo com uma posio na lista; e getView(), que recebe trs parmetros: a sua posio, um View e um ViewGroup, que ser o layout ao qual este objeto pertence. Obtemos o objeto em determinada posio da lista chamando climas.get(position), que no nosso caso ser um Clima. Depois, instanciamos ClimaAdapterView que ser a nossa extenso de LinearLayout. De uma maneira bem simples: a nossa lista conter elementos que sero objetos da classe ClimaAdapterView. Agora criaremos nossa Activity (ClimaAdapterActivity) responsvel por visualizar nosso layout customizado. Observe que ela estende ListActivity pois nossa aplicao utilizar uma lista. Sobrescrevemos onCreate() de ListActivity, que o primeiro mtodo a ser chamado quando a Activity criada. Depois, chamamos o mtodo onCreate() da superclasse e carregamos o layout atual que ser utilizado por meio do mtodo setContentView(). Perceba em main.xml no diretrio res/layout/, (Listagem 12) que nosso layout ser carregado utilizando um <LinearLayout>. Aninhado a este existe a tag <ListView> com o atributo android:id que possui o valor @+id/android:listinformando que a lista a ser carregada ser uma prdefinida pela plataforma. A tag <TextView> representa um texto que mostrar uma mensagem caso no exista nenhum elemento na lista. Essa mensagem referenciada pelo atributo android:text com o valor @string/sem_itens, que est no arquivo strings.xml (Listagem 13). Agora instanciaremos um ArrayList que representar a fonte de dados que

16

passaremos para ClimaAdapter mais frente. Agora, instanciamos e adicionamos na lista (climas) vrios objetos Clima, passando no seu construtor o nome da cidade, a sua temperatura, e o status do clima, respectivamente. Aqui vem uma das partes mais interessantes: instanciamos o objeto ClimaAdapter e passamos em seu construtor a referncia this, representando a ClimaAdapterActivity, e o ArrayList de climas. Finalmente, chamamos o mtodo setListAdaper() e passamos um ClimaAdapter (climaAdapter) como parmetro, responsvel pelo binding com os dados e o elemento que representar a lista. Na Figura 19, podemos visualizar no emulador o estgio final de nosso novo layout em ao. ViewGroup
Gallery GridView ListView ScrollView Spinner

Descrio
Exibe uma lista de imagens (com rolagem para a direita e esquerda). Exibe uma grade com rolagem que possui linhas e colunas. Exibe uma lista de Views (apenas uma coluna). Uma coluna de elementos com rolagem na vertical. Exibe um nico item por vez, de acordo com uma lista de dados, dentro de uma caixa de texto de uma nica linha. Semelhante uma listbox que pode realizar a rolagem horizontalmente ou verticalmente. Permite acesso direto a uma superfcie de desenho, possibilitando que seus filhos sejam dispostos em cima esta superfcie. Porm, este componente deve ser utilizado para aplicaes que desejem desenhar pixels em vez de widgets. Componente que permite que vrias abas sejam adicionadas, selecionadas e que possam reagir a eventos de cliques do mouse. Uma lista que exibe um componente por vez, dentro de uma caixa de texto de uma nica linha. Este componente pode ser configurado para trocar (exibir outro) componente de acordo com determinado intervalo, como se fosse um slideshow. O mesmo que ViewFlipper.

SurfaceView

TabHost ViewFlipper

ViewSwitcher

Tabela 1. Outros Layouts disponveis em Android.

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); } }

Listagem 10. ClimaAdapter.java


package android.clima.adapter; /* imports */ public class ClimaAdapter extends BaseAdapter { private Context context; private List<Clima> climas; /* constructor */ public int getCount() { return climas.size(); } public Object getItem(int position) { return climas.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { Clima clima = climas.get(position); return new ClimaAdapterView(this.context, clima ); } }

Listagem 11. ClimaAdapterActivity.java


package android.clima.adapter; /* imports */ public class ClimaAdapterActivity extends ListActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); ArrayList<Clima> climas = new ArrayList<Clima>(); Clima w = new Clima("Belm", 32, StatusClima.ENSOLARADO); climas.add(w); w = new Clima("So Paulo", 17, StatusClima.NUBLADO);

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); } }

Listagem 12. main.xml


<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ListView android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <TextView android:id="@+id/android:empty" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="@string/sem_itens"/> </LinearLayout>

Listagem 13. strings.xml


<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">ClimaAdapterView</string> <string name="sem_itens">No h itens na lista</string> </resources>

Figura 19. A aplicao carregada utilizando a nossa extenso de LinearLayout.

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

vimos na seo anterior, a plataforma permite que componentes grficos (Views e ViewGroups) sejam criados via cdigo, caso o programador assim desejar. Neste artigo, voc aprendeu como se criar layouts complexos em Android, sendo explicado como a plataforma implementa a hierarquia de componentes de tela e como os componentes respeitam os limites de seus pais. Alm disso, voc aprendeu como reunir os layouts e aninh-los, a fim de construir estruturas grficas mais complexas. Finalmente, foi demonstrado como estender layouts para incrementar a parte de interface grfica da sua aplicao, caso as fornecidas por Android no sejam suficientes. Em um prximo artigo iremos explorar os tipos de recursos (imagens, cores, animaes, estilos, etc) disponveis na plataforma para voc utilizar em seus projetos Android. At a prxima! Links Hierarquia de Componentes de Tela http://code.google.com/android/devel/ui/hierarchy.html Principais Componentes de Layouts http://code.google.com/android/devel/ui/layout.html Documentao de AdapterView http://code.google.com/android/reference/android/widget/AdapterView.html Documentao de Adapter http://code.google.com/android/reference/android/widget/Adapter.html DroidDraw http://droiddraw.org

Você também pode gostar