Antes de começar, havia prometido que iria falar de storyBoard. E ainda vou. O caso é que estou no notebook e não tenho um software aqui para desenhar o storyboard, como o Corel. Na verdade, eu desenho o storyboard numa folha de papel mesmo, mas para efeito do blog, quero desenhá-lo em alguma ferramenta. Ou, dependendo, faço no papel e scanneio, não sei ainda. De qualquer forma, volto a esse assunto em breve.
Seu layout é a arquitetura da interface de usuário em uma atividade. Ele define a estrutura de layout e guarda os elementos que aparecem para o usuário. Você pode declarar seu layout de duas maneiras:
- Declarando os elementos de interface em XML. O Android provê um vocabulário XML fácil que corresponde à classe View e subclasses como widgets e layouts.
- Instanciar elementos de layout em tempo de execução. Sua aplicação pode criar os objetos View e ViewGroup (e manipular suas propriedades) programaticamente.
A framework Android dá a você a flexibilidade de usar ou um deles ou ambos os métodos de declaração e gerenciamento de sua interface de aplicação. Por exemplo, você poderia declarar seu layout de aplicação em XML, incluindo os elementos de tela que vão aparecer neles e suas propriedades. Você poderia então adicionar código em sua aplicação que modificaria o estado dos objetos de tela, incluindo aqueles declarados em XML, em tempo de execução.
A vantagem de declarar a interface em XML é que ela permite a você uma melhor separação da apresentação da sua aplicação do código que controla seu comportamento. As descrições da interface são externas ao seu código de aplicação, o que significa que você pode modificá-lo ou adaptá-lo sem ter de modificar o código fonte e recompilar. Por exemplo, você pode criar layouts XML para orientações diferentes, para diferentes tamanhos de tela e diferentes linguas. Adicionalmente, declarando o layout em XML faz ser mais fácil visualizar a estrutura de sua interface, então é mais fácil debugar problemas.
Em geral, o vocabulário XML para declaração de elementos de interface segue a estrutura e nomeação de classes e métodos, onde os nomes de elementos correspondem aos nomes de classe e nomes de atributos para métodos. De fato, a correspondencia é, na maioria das vezes, tão direta que você pode entender que atributo XML corresponde ao método de classe, ou inquirir qual classe corresponde ao elemento xml dado. Contudo, note que nem todo vocabulário é identico. Em alguns casos, existem diferenças mínimas na nomeação dos atributos e métodos. Por exemplo, o elemento EditText tem um atributo text que corresponde a EditText.setText().
Objetos de Layout Comuns
Os tipos de layout mais comuns são:
FrameLayout
É o mais simples dos tipos de objeto de layout. É basicamente um espaço em branco na tela que você pode preencher com um objeto - por exemplo, uma foto que você quer que seja mostrada. Todos os elementos filhos de um FrameLayout são inseridos no canto esquerdo superior da tela; você não pode especificar uma localização diferente para a view filha. Views filhas subsequentes serão simplesmente desenhadas sobre as views anteriores, particalmente ou totalmente obscurescendo-as (a não ser que o novo objeto seja transparente).
Abaixo um código com FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="Eu sou um TextView"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</FrameLayout>
E o resultado:
Agora outro código com FrameLayout mas com dois componentes dentro do Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="Eu sou um TextView"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<Button
android:text=".."
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</FrameLayout>
E o resultado:
Perceba que o botão ficará por cima do TextView. Como dito acima, o componente subsequente (Button) será desenhado sobre o componente que já existe (TextView).
LinearLayout
Esse layout alinha todos os componentes filhos em uma única direção - verticalmente ou horizontalmente, dependendo em como você define o atributo orientation. Todos os filhos - entenda filho como cada um dos elementos dentro de um layout - são mostrados um após o outro, então uma lista vertical terá apenas um filho por linha, não importa o quão larga a tela seja, e uma lista horizontal vai mostrar uma única linha (com a altura baseada no filho mais alto). Um layout linear respeita as margens entre os filhos e o atributo gravity (alinhamento right, center ou left) de cada filho.
O layout linear também suporta um peso (weight) para cada filho individual. Esse atributo assinala um valor de "importância" para uma view e permite que seja expandida para preencher quaisquer espaços remanescentes na view pai. Views filhas podem especificar um valor de peso baseado num integer e então qualquer espaço remanescente na viewGroup é assinalado ao filho na proporção do peso declarado. O peso padrão é zero.
Difícil entender, né? Nem tanto. Por exemplo, se existem três text boxes e dois deles declaram um peso de 1, enquanto ao outro é dado peso de 0, o terceiro textbox sem um peso não vai crescer e vai apenas ocupar a área ocupada pelo seu conteúdo. Os outros text boxes vão igualmente preencher o espaço remanescente. Se o terceiro textbox é dado um peso de 2 ao invés de 0, então ele é declarado como mais importante que os outros dois text boxes e então ele terá metade do total do espaço da tela, enquanto os outros compartilham a outra metade da tela em iguais pedaços.
Basicamente esse sistema de pesos permite que você possa dividir o espaço da tela. No exemplo acima, havendo dois text boxes com peso 1 e um com peso 0, o que o sistema Android fará é o seguinte: ele pegará o textbox sem peso e calculará o espaço que ele ocupará na tela, de acordo com o seu conteúdo. Digamos que o conteúdo ocupe 10% da tela. Os outros dois text boxes terão 90% da tela para dividir entre si. Como ambas têm peso 1, ambas receberão 45% do restante da tela.
Mas, tendo o terceiro textbox peso 2 e os dois primeiros peso 1, fica mais fácil calcular. Basta somar os pesos de todos os componentes, que totalizam, nesse caso, 4. Como o terceiro textbox tem peso 2, ele terá 50% da tela. Os outros dois text boxes, portanto, terão 25% da tela.
Ou seja, colocando pesos nos componentes ficar mais fácil calcular a divisão na tela.
Abaixo um código usando linearLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="Eu sou um TextView"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<Button
android:text=".."
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
E o resultado:
Perceba como os componentes estão um abaixo do outro, dado que a orientação é vertical no código acima.
TableLayout
Esse layout posiciona seus filhos em linhas e colunas. Os conteiners do TableLayout não mostram bordas para linhas, colunas ou células. As tabelas podem conter quantas colunas, linhas ou células você quiser. No entanto, as células não permitem usar a propriedade span, como acontece em HTML.
Objetos TableRow são as views filhas de uma TableLayout (cada TableRow define uma linha na tabela). Cada linha tem zero ou mais células, onde cada uma delas é dada por um tipo de view diferente (TextView ou ImageView, por exemplo). Uma célula ser um objeto ViewGroup, onde você poderá aninhar outra TableLayout como uma célula.
Eu disse anteriormente que apenas um tipo de Layout poderia ser colocada numa View. E é isso mesmo. Apenas um tipo de Layout pode ser colocado numa view. Se dois TableLayouts, por exemplo, estiverem numa view, elas obrigatoriamente virão uma aninhada à outra.
Você pode colocar o seguinte código que funcionará:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TableLayout
android:id="@+id/tableLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TableLayout>
</TableLayout>
Mas se eu colocar um código assim:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
</TableLayout>
<TableLayout
android:id="@+id/tableLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TableLayout>
Eu terei o seguinte erro:
Veja o seguinte código abaixo:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="TextView1"
android:padding="3dip" />
<TextView
android:text="TextView2"
android:gravity="right"
android:padding="3dip" />
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:text="TextView3"
android:padding="3dip" />
<TextView
android:text="TextView4"
android:gravity="right"
android:padding="3dip" />
</TableRow>
</TableLayout>
E o resultado:
RelativeLayout
Esse tipo de layout permite aos filhos especificar posições relativas à visão pai ou relativa a outro elemento (especificado pelo ID). Então você pode alinhar dois elementos pela borda direita, ou fazer um atrás do outro, centralizado na tela, centralizado à esquerda e assim por diante. Elementos são renderizado a partir do primeiro elemento. Então, se esse elemento está alinhado ao centro da tela, os outros elementos alinham-se a esse elemento relativo ao centro da tela. Ainda mais, por conta dessa ordenação, se você estiver usando XML para especificar o layout, o elemento que você referenciar (para que possa posicionar os outros elementos) deve ser listado no XML antes de ser referido em outras views.
Veja o código abaixo:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10px" >
<TextView android:id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Type here:" />
<EditText android:id="@+id/entry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/label" />
<Button android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10px"
android:text="OK" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />
</RelativeLayout>
E o resultado
Veja que o alinhamento dos elementos é dado em funcção das configurações como _alignParentRight, _toLeftOf, etc.
Ok. Eu já sei como são os layouts. E ai?
Agora você tem de escrever o XML na pasta res/layout. Basta isso para criar a interface. Simples, não?
Carregando o recurso XML
Quando você compila a aplicação, cada layout XML é complicado em um recurso View. Você deverá carregar o recurso layout a partir do código da aplicação, em sua implementação Activity.onCreate(). Faça isso chamando setContentView(), passando a sua referencia para o recurso de layout na forma de R.layout.nome_do_layout. Por exemplo, se o seu layout é chamado de main.xml, você deverá carregar a sua atividade tal como abaixo:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }
Quando você chama setContentView() passando uma referência de recurso de layout, a atividade infla o recurso na tela e a tela pode, então, ser desenhada pelo sistema Android.
Bem, por enquanto é isso. No próximo post eu falarei como desenhar as telas usando o Eclipse.