Tutorial Android #6 – Utilizando Abas

Padrão

Olá pessoal! 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):

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.

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<Restaurante> listaRestaurantes = new ArrayList<Restaurante>();
	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<Restaurante> {
		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);
			}
		}
	}
}

Se você perdeu alguma coisa, ou quer baixar o projeto, só clicar aqui.

Até a próxima! 🙂

3 comentários sobre “Tutorial Android #6 – Utilizando Abas

  1. Joao

    quando adiciono um restaurante e depois vou a aba da lista ela fica iguala aba detalhes alguma solução? tentei com o projecto daqui e acontece o mesmo

  2. David Augusto GC

    Onde fica o conteudo do post, esta estreito, aumenta a width dessa parte! tem muita parte vazia…ta sobrando espaço, e onde esta o post, esta estreito… os codigos, mal da para enxergar, tem q ficar indo para os lados toda hora, issop é ruim para quem ta lendo!

  3. Cafer

    Tentei abrir o projeto no Android Studio e não consigo visualizar o projeto, apenas aparece 3 classes (BuildConfig; Manifest;R) Consegue me orientar como abrir?

Deixe uma resposta