Caso prefira, você encontrará todo esse material, em inglês, no site do Developer Android. A tradução e comentários dos materiais eu faço livremente para ajudar a comunidade que fala português.

sexta-feira, 25 de fevereiro de 2011

Interface de Usuário - Declarando o Layout

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.

2 comentários:

Ana Paula Gomes disse...

Oi Leonardo, parabéns pelo blog! Várias dúvidas minhas foram tiradas a partir das postagens. O blog já está dentre os meus favoritos. Sucesso!

Leonardo Nakahara disse...

Obrigado Ana Paula. O intuito é esse mesmo, o de ajudar a comunidade que deseja aprender Android mas que não domina o inglês.

Abraços!

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Related Posts Plugin for WordPress, Blogger...