Android

25 jul, 2011

Usando Layout Weights – Parte 02

Publicidade

No artigo anterior, nós vimos como usar layout_weight para dar um controle fino sobre a forma de dispor conteúdo dentro de um layout pai. Neste artigo vamos falar mais sobre alguns aspectos de layout_weights.

Continuando de onde paramos no último artigo, há uma outra coisa que podemos fazer e que nos dá ainda mais controle. Até agora temos usado layout_weights para dividir proporcionalmente um layout baseado no valor total de todos os layout_weights de seus filhos.

No último exemplo, os pesos foram 2 e 1, respectivamente, de modo que o total é de 3 e 2/3 do espaço vai para o primeiro e 1/3 para o segundo. Podemos sobrescrever este comportamento, adicionando um weightSum ao layout do pai:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#FFFF00"
android:weightSum="4">
<LinearLayout android:background="#FF0000"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_weight="2" />
<LinearLayout android:background="#00FF00"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_weight="1" />
</LinearLayout>

Aqui estamos dando ao layout pai um weightSum de 4, e configurando sua cor para amarelo:

Os layouts são divididas como antes, mas como demos ao layout pai um weightSum de 4, o layout vermelho fica com 2/4 (ou seja, metade do espaço). O layout verde fica com 1/4 (metade da área remanescente) e o layout pai (amarelo) aparece no o 1/4 inferior da tela, provando que ainda preenche toda a tela (match_parent).

Agora vamos ver como podemos usar layout_weight de uma forma ligeiramente diferente. Suponha que queiramos um layout onde temos um cabeçalho de tamanho fixo na parte superior, um rodapé de tamanho fixo na parte inferior e um corpo que vai se expandir no espaço restante entre o cabeçalho e o rodapé.

Enquanto poderíamos fazer isso usando posicionamento absoluto (em pixels) para dispositivos individuais, com layout_weight podemos fazer isso automaticamente para todos os dispositivos:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:background="#FF0000"
android:layout_height="50dp" android:layout_width="match_parent" />
<LinearLayout android:background="#00FF00"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_weight="1" />
<LinearLayout android:background="#0000FF"
android:layout_height="50dp" android:layout_width="match_parent" />
</LinearLayout>

Aqui estamos definindo uma altura fixa para o cabeçalho e o rodapé (poderiamos utilizar wrap_content caso eles tivessem conteúdo). Vamos estabelecer também um layout_weight na seção central da tela (cor verde).

Como esse é o único “filho” com um layout_weight, ele será expandido para ocupar toda área remanescente após os outros filhos (cabeçalho e rodapé) serem posicionados:

Vamos concluir com outra pegadinha trabalhando com larguras de layout. É só mudar para um LinearLayout horizontal, contendo dois TextViews, cada um com um layout_weight a 1 – mas com textos de comprimentos diferentes um do outro:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_height="wrap_content" android:text="s"
android:layout_width="wrap_content" android:layout_weight="1" />
<TextView android:layout_height="wrap_content"
android:text="This contains some much longer text"
android:layout_width="wrap_content" android:layout_weight="1" />
</LinearLayout>

Seria de esperar que ambos os TextView ganhassem metade do espaço na tela, mas quando executamos esse layout obtemos:

O TextView com o texto mais longo está recebendo mais espaço na tela apesar de termos dado pesos iguais para ambos textos. Isto ocorre porque quando é feito o calculo do layout, o tamanho dos TextView são calculados com o tamanho necessário para o texto (wrap_content). O espaço restante é dividido de forma igual entro os dois devido ao layout_weight.

Como o segundo TextView é mais amplo (devido ao seu texto maior), ele parece estar levando vantagem no cálculo dos pesos dos layouts. Mas há um jeito fácil de resolver isso, basta definirmos a largura (layout_width) em ambos os TextView para “0dp” para evitar que o tamanho do texto influencie no cálculo do layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_height="wrap_content" android:text="s"
android:layout_width="0dp" android:layout_weight="1" />
<TextView android:layout_height="wrap_content"
android:text="This contains some much longer text"
android:layout_width="0dp" android:layout_weight="1" />
</LinearLayout>

O espaço disponível agora é dividido igualmente entre eles, forçando o segundo TextView a ter duas linhas:

Para finalizar, vale lembrar que layout_weight pode ser usado com outros layouts e views que estendem o LinearLayout, como por exemplo o RadioGroup.

Observação: Este texto é uma adaptação do original Layout Weights – Part 2 de Mark Allison, feita sob a expressa autorização do autor.