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:

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

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(&quot;tag1&quot;);<br />
descritor.setContent(R.id.restaurantes);<br />
descritor.setIndicator(&quot;Lista&quot;, getResources().getDrawable(R.drawable.lista));<br />
getTabHost().addTab(descritor);</p>
<p>descritor = getTabHost().newTabSpec(&quot;tag2&quot;);<br />
descritor.setContent(R.id.detalhes);<br />
descritor.setIndicator(&quot;Detalhes&quot;, getResources().getDrawable(R.drawable.restaurante));<br />
getTabHost().addTab(descritor);</p>
<p>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() {<br />
	public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position,<br />
			long id) {</p>
<p>	}<br />
};

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;<br />
EditText endereco = null;<br />
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);<br />
endereco = (EditText) findViewById(R.id.end);<br />
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() {<br />
	public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position,<br />
			long id) {<br />
		Restaurante r = listaRestaurantes.get(position);<br />
		nome.setText(r.getNome());<br />
		endereco.setText(r.getEndereco());</p>
<p>		if (r.getTipo().equals(&quot;rodizio&quot;)) {<br />
			tipos.check(R.id.rodizio);<br />
		} else if (r.getTipo().equals(&quot;fast_food&quot;)) {<br />
			tipos.check(R.id.fast_food);<br />
		} else {<br />
			tipos.check(R.id.a_domicilio);<br />
		}<br />
	}<br />
};

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

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

Até a próxima! 🙂