07 - Criando abas no Android

Aprenda a trabalhar com abas nos seus aplicativos para Android.

Por | @http://twitter.com/_rafaeltoledo Programação

No último post da série, adicionamos uma listagem com os restaurantes adicionados, mostrando um ícone indicando o tipo de restaurante, além do endereço. Hoje vamos separar a listagem do formulário, colocando uma aba para cada um.

O primeiro passo é modificar o nosso arquivo de layout main.xml, retirando o RelativeLayout e adicionando os itens TabHost, TabWidget e FrameLayout, que acomodarão nossos itens. Assim, o nosso novo arquivo main.xml ficará assim:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
        <TabWidget android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
        <FrameLayout android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
            <ListView android:id="@+id/restaurantes"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"/>
            <TableLayout android:id="@+id/detalhes"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:stretchColumns="1"
                android:paddingTop="4dip">
                <TableRow>
                    <TextView android:text="Nome:"/>
                    <EditText android:id="@+id/nome"/>
                </TableRow>
                <TableRow>
                    <TextView android:text="Endereço:"/>
                    <EditText android:id="@+id/end"/>
                </TableRow>
                <TableRow>
                    <TextView android:text="Tipo:"/>
                    <RadioGroup android:id="@+id/tipos">
                        <RadioButton android:id="@+id/rodizio"
                            android:text="Rodízio"/>
                        <RadioButton android:id="@+id/fast_food"
                            android:text="Fast Food"/>
                        <RadioButton android:id="@+id/a_domicilio"
                            android:text="A Domicílio"/>
                    </RadioGroup>
                </TableRow>
                <Button android:id="@+id/salvar"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:text="Salvar"/>
            </TableLayout>
        </FrameLayout>
    </LinearLayout>
</TabHost> 

O único detalhe que podemos salientar sobre esse novo layout, é o atributo identificador nos nós relativos às abas. @android:id/tabhost, @android:id/tabs e @android:id/tabcontent referem-se aos elementos da própria estrutura que possuem tais nomes. Por isso essa maneira “diferente” de definir este atributo (e por esse motivo não podemos alterar seus identificadores).

O próximo passo é modificar a nossa classe ListaRestaurantes para estender TabActivity, e mostrar ao TabHost como utilizar o conteúdo de nosso FrameLayout. Além disso, precisaremos de dois novos ícones, que serão exibidos para identificar cada uma das abas (lista.png e restaurante.png). Assim, primeiramente alteramos a definição da nossa classe (lembrando que pra corrigir os imports no Eclipse, é só pressionar Ctrl + Shift + O):

O único detalhe que podemos salientar sobre esse novo layout, é o atributo identificador nos nós relativos às abas. @android:id/tabhost, @android:id/tabs e @android:id/tabcontent referem-se aos elementos da própria estrutura que possuem tais nomes. Por isso essa maneira “diferente” de definir este atributo (e por esse motivo não podemos alterar seus identificadores).

O próximo passo é modificar a nossa classe ListaRestaurantes para estender TabActivity, e mostrar ao TabHost como utilizar o conteúdo de nosso FrameLayout. Além disso, precisaremos de dois novos ícones, que serão exibidos para identificar cada uma das abas (lista.png e restaurante.png). Assim, primeiramente alteramos a definição da nossa classe (lembrando que pra corrigir os imports no Eclipse, é só pressionar Ctrl + Shift + O):

public class ListaRestaurantes extends TabActivity {

Agora, vamos adicionar um trecho de código ao nosso método onCreate(), para que as abas funcionem corretamente. Adicione o seguinte trecho ao final do método onCreate:

TabSpec descritor = getTabHost().newTabSpec("tag1");
descritor.setContent(R.id.restaurantes);
descritor.setIndicator("Lista", getResources().getDrawable(R.drawable.lista));
getTabHost().addTab(descritor);
 
descritor = getTabHost().newTabSpec("tag2");
descritor.setContent(R.id.detalhes);
descritor.setIndicator("Detalhes", getResources().getDrawable(R.drawable.restaurante));
getTabHost().addTab(descritor);
 
getTabHost().setCurrentTab(0);

Se executarmos nossa aplicação neste momento, ela já terá a estrutura que definimos até o momento funcionando.

07 - Criando abas no Android

07 - Criando abas no Android

Continuando, precisamos adicionar uma forma de, quando o usuário tocar sobre um dos restaurantes listados, ele possa editar suas informações no formulário. Para isso, vamos criar um listener que responda a esse evento, possibilitando manipular tal evento e realizar as tarefas necessárias. Portanto, criamos um listener OnItemClickListener em nossa classe:

private OnItemClickListener onListClick = new OnItemClickListener() {
   public void onItemClick(AdapterView parent, View view, int position,long id) {
 
   }
};

Ah, e não se esqueça de adicionar este listener no método onCreate().

lista.setOnItemClickListener(onListClick);

Agora, vamos fazer com que o formulário seja atualizado quando o clique (toque) for feito. Vamos criar, primeiramente, 3 atributos em nossa classe que armazenarão os valores dos campos:

EditText nome = null;
EditText endereco = null;
RadioGroup tipos = null;

Em seguida, logo após a chamada ao método setContentView() no método onCreate(), adicione as seguintes linhas:

nome = (EditText) findViewById(R.id.nome);
endereco = (EditText) findViewById(R.id.end);
tipos = (RadioGroup) findViewById(R.id.tipos);

Agora, vamos adicionar o corpo do método onItemClick(), para atualizar o formulário com base nos dados do item clicado.

private OnItemClickListener onListClick = new OnItemClickListener() {
   public void onItemClick(AdapterView parent, View view, int position,long id) {
      Restaurante r = listaRestaurantes.get(position);
      nome.setText(r.getNome());
      endereco.setText(r.getEndereco());
 
      if (r.getTipo().equals("rodizio")) {
         tipos.check(R.id.rodizio);
      } else if (r.getTipo().equals("fast_food")) {
         tipos.check(R.id.fast_food);
      } else {
         tipos.check(R.id.a_domicilio);
     }
   }
};

Por fim, adicionamos, também ao método onItemClick(), a chamada ao método para mudar a aba.

getTabHost().setCurrentTab(1);

E pronto! Nosso exemplo está funcionando! A listagem completa da classe ListaRestaurantes é essa:

package net.rafaeltoledo.restaurante;
 
import java.util.ArrayList;
import java.util.List;
 
import net.rafaeltoledo.restaurante.model.Restaurante;
import android.app.TabActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
 
public class ListaRestaurantes extends TabActivity {
 
    List listaRestaurantes = new ArrayList();
    AdaptadorRestaurante adaptador = null;
 
    EditText nome = null;
    EditText endereco = null;
    RadioGroup tipos = null;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        nome = (EditText) findViewById(R.id.nome);
        endereco = (EditText) findViewById(R.id.end);
        tipos = (RadioGroup) findViewById(R.id.tipos);
 
        Button salvar = (Button) findViewById(R.id.salvar);
        salvar.setOnClickListener(onSave);
 
        ListView lista = (ListView) findViewById(R.id.restaurantes);
        adaptador = new AdaptadorRestaurante();
        lista.setAdapter(adaptador);
        lista.setOnItemClickListener(onListClick);
 
        TabSpec descritor = getTabHost().newTabSpec("tag1");
        descritor.setContent(R.id.restaurantes);
        descritor.setIndicator("Lista", getResources().getDrawable(R.drawable.lista));
        getTabHost().addTab(descritor);
 
        descritor = getTabHost().newTabSpec("tag2");
        descritor.setContent(R.id.detalhes);
        descritor.setIndicator("Detalhes", getResources().getDrawable(R.drawable.restaurante));
        getTabHost().addTab(descritor);
 
        getTabHost().setCurrentTab(0);
    }
 
    private OnItemClickListener onListClick = new OnItemClickListener() {
        public void onItemClick(AdapterView parent, View view, int position,long id) {
            Restaurante r = listaRestaurantes.get(position);
            nome.setText(r.getNome());
            endereco.setText(r.getEndereco());
 
           if (r.getTipo().equals("rodizio")) {
               tipos.check(R.id.rodizio);
           } else if (r.getTipo().equals("fast_food")) {
               tipos.check(R.id.fast_food);
           } else {
               tipos.check(R.id.a_domicilio);
        }
 
        getTabHost().setCurrentTab(1);
    }
 };
 
 private OnClickListener onSave = new OnClickListener() {
 
    public void onClick(View arg0) {
        Restaurante r = new Restaurante();
        EditText nome = (EditText) findViewById(R.id.nome);
        EditText endereco = (EditText) findViewById(R.id.end);
 
        r.setNome(nome.getText().toString());
        r.setEndereco(endereco.getText().toString());
 
        RadioGroup tipos = (RadioGroup) findViewById(R.id.tipos);
 
        switch (tipos.getCheckedRadioButtonId()) {
             case R.id.rodizio:
                 r.setTipo("rodizio");
             break;
             case R.id.fast_food:
                 r.setTipo("fast_food");
             break;
             case R.id.a_domicilio:
                 r.setTipo("a_domicilio");
             break;
        }
 
        adaptador.add(r);
    }
 };
 
 class AdaptadorRestaurante extends ArrayAdapter {
    AdaptadorRestaurante() {
        super(ListaRestaurantes.this, R.layout.linha,listaRestaurantes);
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
 
        View linha = convertView;
        ArmazenadorRestaurante armazenador = null;
 
        if (linha == null) {
            LayoutInflater inflater = getLayoutInflater();
            linha = inflater.inflate(R.layout.linha, parent, false);
            armazenador = new ArmazenadorRestaurante(linha);
            linha.setTag(armazenador);
        } else {
            armazenador = (ArmazenadorRestaurante) linha.getTag();
        }
 
        armazenador.popularFormulario(listaRestaurantes.get(position));
 
        return linha;
    }
 }
 
 static class ArmazenadorRestaurante {
    private TextView nome = null;
    private TextView endereco = null;
    private ImageView icone = null;
 
    ArmazenadorRestaurante(View linha) {
        nome = (TextView) linha.findViewById(R.id.titulo);
        endereco = (TextView) linha.findViewById(R.id.endereco);
        icone = (ImageView) linha.findViewById(R.id.icone);
    }
 
    void popularFormulario(Restaurante r) {
        nome.setText(r.getNome());
        endereco.setText(r.getEndereco());
 
        if (r.getTipo().equals("rodizio")) {
            icone.setImageResource(R.drawable.rodizio);
        } else if (r.getTipo().equals("fast_food")) {
            icone.setImageResource(R.drawable.fast_food);
        } else {
            icone.setImageResource(R.drawable.entrega);
        }
    }
 }
}

Faça download dos arquivos do projeto:

07 - Criando abas no Android

Mais sobre: guiaandroid
Share Tweet
Mais compartilhados
Comentários