Tutorial Android 4 #8 – Utilizando Abas

Padrão

Olá pessoal! No último post da série, adicionamos uma listagem com os contatos adicionados, mostrando um ícone indicando o tipo de contato, além do seu respectivo 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 activity_meus_contatos.xml, retirando o LinearLayout e adicionando os itens TabHostTabWidget e FrameLayout, que acomodarão nossos itens. Assim, o nosso novo arquivo activity_meus_contatos.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;@+id/tabhost&quot;<br />
    android:layout_width=&quot;match_parent&quot;<br />
    android:layout_height=&quot;match_parent&quot; &gt;</p>
<p>    &lt;LinearLayout<br />
        android:layout_width=&quot;match_parent&quot;<br />
        android:layout_height=&quot;match_parent&quot;<br />
        android:orientation=&quot;vertical&quot; &gt;</p>
<p>        &lt;TabWidget<br />
            android:id=&quot;@android:id/tabs&quot;<br />
            android:layout_width=&quot;match_parent&quot;<br />
            android:layout_height=&quot;wrap_content&quot; /&gt;</p>
<p>        &lt;FrameLayout<br />
            android:id=&quot;@android:id/tabcontent&quot;<br />
            android:layout_width=&quot;match_parent&quot;<br />
            android:layout_height=&quot;match_parent&quot; &gt;</p>
<p>            &lt;ListView<br />
                android:id=&quot;@+id/contatos&quot;<br />
                android:layout_width=&quot;match_parent&quot;<br />
                android:layout_height=&quot;match_parent&quot; /&gt;</p>
<p>            &lt;RelativeLayout<br />
                android:id=&quot;@+id/detalhes&quot;<br />
                android:layout_width=&quot;fill_parent&quot;<br />
                android:layout_height=&quot;wrap_content&quot; &gt;</p>
<p>                &lt;LinearLayout<br />
                    android:layout_width=&quot;match_parent&quot;<br />
                    android:layout_height=&quot;wrap_content&quot;<br />
                    android:layout_alignParentTop=&quot;true&quot;<br />
                    android:orientation=&quot;vertical&quot; &gt;</p>
<p>                    &lt;TextView<br />
                        android:layout_width=&quot;wrap_content&quot;<br />
                        android:layout_height=&quot;wrap_content&quot;<br />
                        android:text=&quot;@string/nome&quot; /&gt;</p>
<p>                    &lt;EditText<br />
                        android:id=&quot;@+id/nome&quot;<br />
                        android:layout_width=&quot;fill_parent&quot;<br />
                        android:layout_height=&quot;wrap_content&quot;<br />
                        android:inputType=&quot;text&quot; /&gt;</p>
<p>                    &lt;TextView<br />
                        android:layout_width=&quot;wrap_content&quot;<br />
                        android:layout_height=&quot;wrap_content&quot;<br />
                        android:text=&quot;@string/email&quot; /&gt;</p>
<p>                    &lt;EditText<br />
                        android:id=&quot;@+id/email&quot;<br />
                        android:layout_width=&quot;fill_parent&quot;<br />
                        android:layout_height=&quot;wrap_content&quot;<br />
                        android:inputType=&quot;textEmailAddress&quot; /&gt;</p>
<p>                    &lt;TextView<br />
                        android:layout_width=&quot;wrap_content&quot;<br />
                        android:layout_height=&quot;wrap_content&quot;<br />
                        android:text=&quot;@string/tipo_contato&quot; /&gt;</p>
<p>                    &lt;RadioGroup<br />
                        android:id=&quot;@+id/tipo_contato&quot;<br />
                        android:layout_width=&quot;fill_parent&quot;<br />
                        android:layout_height=&quot;wrap_content&quot; &gt;</p>
<p>                        &lt;RadioButton<br />
                            android:id=&quot;@+id/pessoal&quot;<br />
                            android:layout_width=&quot;wrap_content&quot;<br />
                            android:layout_height=&quot;wrap_content&quot;<br />
                            android:text=&quot;@string/tipo_pessoal&quot; /&gt;</p>
<p>                        &lt;RadioButton<br />
                            android:id=&quot;@+id/profissional&quot;<br />
                            android:layout_width=&quot;wrap_content&quot;<br />
                            android:layout_height=&quot;wrap_content&quot;<br />
                            android:text=&quot;@string/tipo_profissional&quot; /&gt;</p>
<p>                        &lt;RadioButton<br />
                            android:id=&quot;@+id/academico&quot;<br />
                            android:layout_width=&quot;wrap_content&quot;<br />
                            android:layout_height=&quot;wrap_content&quot;<br />
                            android:text=&quot;@string/tipo_academico&quot; /&gt;<br />
                    &lt;/RadioGroup&gt;<br />
                &lt;/LinearLayout&gt;</p>
<p>                &lt;Button<br />
                    android:id=&quot;@+id/salvar&quot;<br />
                    android:layout_width=&quot;fill_parent&quot;<br />
                    android:layout_height=&quot;wrap_content&quot;<br />
                    android:layout_alignParentBottom=&quot;true&quot;<br />
                    android:text=&quot;@string/salvar&quot; /&gt;<br />
            &lt;/RelativeLayout&gt;<br />
        &lt;/FrameLayout&gt;<br />
    &lt;/LinearLayout&gt;</p>
<p>&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 chaves do layout de abas, que possuem tais nomes internamente no Android. Assim, precisamos colocar esses ids para que o layout seja montado corretamente (e por esse motivo não podemos alterar seus identificadores).

O próximo passo é modificar o nosso o método onCreate da classe MeusContatos para carregar o layout de abas e dividir o conteúdo entre elas. Carregamos o nosso TabHost e, a partir dele, criamos as outras abas programaticamente. Adicione o seguinte código logo após a chamada ao setContentView().

TabHost abas = (TabHost) findViewById(R.id.tabhost);<br />
abas.setup();</p>
<p>TabSpec descritor = abas.newTabSpec(&quot;aba1&quot;);<br />
descritor.setContent(R.id.contatos);<br />
descritor.setIndicator(getString(R.string.contatos));<br />
abas.addTab(descritor);</p>
<p>descritor = abas.newTabSpec(&quot;aba2&quot;);<br />
descritor.setContent(R.id.detalhes);<br />
descritor.setIndicator(getString(R.string.detalhes));<br />
abas.addTab(descritor);

Criamos, então, duas abas, uma com o título de Contatos e a outra com o título de Detalhes. Ah, lembrem-se de criar as duas strings lá no nosso arquivo strings.xml! Isso para, posteriormente, podermos facilmente internacionalizar nosso aplicativo 🙂

Se executarmos neste momento nosso aplicativo, ele já terá o visual que desejamos:

tutorial-android-01tutorial-android-02

Continuando, precisamos adicionar uma forma de que, quando o usuário tocar sobre um dos contatos da lista, ele possa editar suas informações no formulário. Para isso, vamos criar fazer a nossa classe implementar mais um listener, o OnItemClickListener, para que tenhamos um feedback para esse evento, possibilitando manipulá-lo e realizar as tarefas necessárias. Portanto, vamos fazer a nossa classe implementar tal listener e vamos implementar o método que a interface exige.

public class MeusContatos extends Activity implements OnClickListener, OnItemClickListener {

@Override<br />
public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position, long id) {<br />
}

Agora, vamos adicionar a nossa classe como listener da lista.

lista.setOnItemClickListener(this);

Por organização, vamos fazer uma separação dos elementos de interface, colocando-os como atributos da nossa classe. Isso nos ajudará a deixá-la mais organizada e facilitará a implementação da funcionalidade de editar um registro ao clicar em um item da lista. Dessa forma, vamos adicionar os quatro elementos assim:

private List&lt;Contato&gt; contatos = new ArrayList&lt;Contato&gt;();<br />
private ContatoAdapter adaptador = null;</p>
<p>private TabHost abas = null;<br />
private EditText nome = null;<br />
private EditText email = null;<br />
private RadioGroup tipoContato = null;<br />
private Button salvar = null;

Em seguida, vamos editar o método onCreate() para que inicialize estas variáveis para nós.

@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
	super.onCreate(savedInstanceState);<br />
	setContentView(R.layout.activity_meus_contatos);</p>
<p>	abas = (TabHost) findViewById(R.id.tabhost);<br />
	abas.setup();</p>
<p>	TabSpec descritor = abas.newTabSpec(&quot;aba1&quot;);<br />
	descritor.setContent(R.id.contatos);<br />
	descritor.setIndicator(getString(R.string.contatos));<br />
	abas.addTab(descritor);</p>
<p>	descritor = abas.newTabSpec(&quot;aba2&quot;);<br />
	descritor.setContent(R.id.detalhes);<br />
	descritor.setIndicator(getString(R.string.detalhes));<br />
	abas.addTab(descritor);</p>
<p>	salvar = (Button) findViewById(R.id.salvar);<br />
	salvar.setOnClickListener(this);</p>
<p>	nome = (EditText) findViewById(R.id.nome);<br />
	email = (EditText) findViewById(R.id.email);</p>
<p>	tipoContato = (RadioGroup) findViewById(R.id.tipo_contato);</p>
<p>	ListView lista = (ListView) findViewById(R.id.contatos);<br />
	adaptador = new ContatoAdapter();<br />
	lista.setAdapter(adaptador);<br />
	lista.setOnItemClickListener(this);<br />
}

Como transferimos a inicialização dos componentes para o método onCreate(), podemos retirá-la do método onClick(), deixando-o mais leve:

@Override<br />
public void onClick(View v) {<br />
	Contato contato = new Contato();<br />
	contato.setNome(nome.getText().toString());<br />
	contato.setEmail(email.getText().toString());</p>
<p>	switch (tipoContato.getCheckedRadioButtonId()) {<br />
	case R.id.pessoal:<br />
		contato.setTipo(Contato.Tipo.PESSOAL);<br />
		break;<br />
	case R.id.profissional:<br />
		contato.setTipo(Contato.Tipo.PROFISSIONAL);<br />
		break;<br />
	case R.id.academico:<br />
		contato.setTipo(Contato.Tipo.ACADEMICO);<br />
		break;<br />
	}</p>
<p>	adaptador.add(contato);<br />
}

Vamos, então adicionar a implementação do método onItemClick(), para atualizar o formulário com base nos dados do item clicado.

@Override<br />
public void onItemClick(AdapterView&lt;?&gt; parent, View view, int position, long id) {<br />
	Contato c = contatos.get(position);<br />
	nome.setText(c.getNome());<br />
	email.setText(c.getEmail());</p>
<p>	switch (c.getTipo()) {<br />
	case ACADEMICO:<br />
		tipoContato.check(R.id.academico);<br />
		break;<br />
	case PESSOAL:<br />
		tipoContato.check(R.id.pessoal);<br />
		break;<br />
	case PROFISSIONAL:<br />
		tipoContato.check(R.id.profissional);<br />
		break;<br />
	}</p>
<p>	abas.setCurrentTab(1);<br />
}

Neste método simplesmente obtemos o objeto do tipo Contato que foi clicado e injetamos seus dados nos elementos da tela, mudando para a aba do formulário logo em seguida.

Por fim, vamos fazer um pequeno ajuste no método onClick(), para que ele limpe o formulário e mude para a listagem ao se salvar o contato. Para auxiliar, vamos criar um método limparFormulario() para facilitar o entendimento do código:

@Override<br />
public void onClick(View v) {<br />
	Contato contato = new Contato();<br />
	contato.setNome(nome.getText().toString());<br />
	contato.setEmail(email.getText().toString());</p>
<p>	switch (tipoContato.getCheckedRadioButtonId()) {<br />
	case R.id.pessoal:<br />
		contato.setTipo(Contato.Tipo.PESSOAL);<br />
		break;<br />
	case R.id.profissional:<br />
		contato.setTipo(Contato.Tipo.PROFISSIONAL);<br />
		break;<br />
	case R.id.academico:<br />
		contato.setTipo(Contato.Tipo.ACADEMICO);<br />
		break;<br />
	}</p>
<p>	adaptador.add(contato);</p>
<p>	abas.setCurrentTab(0);<br />
	limparFormulario();<br />
}</p>
<p>private void limparFormulario() {<br />
	nome.setText(&quot;&quot;);<br />
	email.setText(&quot;&quot;);<br />
	tipoContato.check(0);<br />
}

E é isso! Nosso sistema tem um pequeno bug de duplicar o contato ao editá-lo, mas fiquem tranquilos pois vamos corrigi-lo logo logo! 🙂

Pra quem precisar, pode baixar o código do projeto aqui. Até a próxima!