domingo, 12 de julho de 2015

Android - Criando Abas com TabHost e TabSpec




Neste artigo irei abordar um tema muito usual em praticamente todos os sistemas que trabalhei até hoje, ensinarei de uma forma prática como devemos implementar o uso de Abas no sistema Android. Todo desenvolvedor já teve a necessidade de separar os dados por categorias em uma mesma tela, como por exemplo: Tipos de Pessoas: Jurídica e Física, em um cadastro de cliente, podemos também ter a necessidade de criar abas para separar dados cadastrais e financeiros ou até mesmo em um pedido de venda, em se tratando de dispositivos móveis, temos que nos virar para encaixar diversas informações em uma única tela, nestes casos o uso de Abas se torna primordial e indispensável. Como de costume, antes de partir para a parte prática, irei discorrer sobre as classes e os principais métodos utilizados para o desenvolvimento do artigo. Para obtermos este efeito em nosso aplicativo, teremos como base as classes:”TabHost” e “TabSpec” e herdaremos nossa atividade da “TabActivity” e implementaremos os “OnTabChangeListener” e “TabContentFactory” para herdar múltiplos tipos de Interface. Aproveitaremos também este artigo para criar o layout proposto de uma forma dinâmica, veremos mais detalhes adiante.

Classe “TabHost”

Esta classe herda da “FrameLayout” e é denominada como um container para uma visão de janela com guias. Possui dois objetos principais, sendo: um conjunto de “Labels” para que o usuário possa clicar para selecionar uma guia específica e um Objeto FrameLayout que exibe o conteúdo da página. Os elementos individuais normalmente são controlados usando este objeto recipiente, em vez de definir os valores sobre os próprios elementos filho.

Métodos

1-) getTabHost(): Este método retorna o tabHost da atividade que está utilizando para armazenar as guias.
2-) setOnTabChangedListener():  Temos como parâmetro o contexto atual (this). Este método é disparado quando qualquer um dos itens da guia é selecionado ou alterado.
3-) addTab(): Serve para adicionar uma Guia. Possui como parâmetro o objeto da classe “TabSpec”, o qual especifica o conteúdo.
4-) newtabSpec(): Método para definir propriedades para a guia. Possui como retorno um objeto do tipo “TabSpec”. (Classe abordada no próximo tópico)

Exemplo: TabSpec tabSpec1 = tabHost.newTabSpec("Pessoa Fisica");

Classe “TabSpec”

Responsável por possuir um indicador de guia, conteúdo e disponibiliza uma marca para usar e manter o controle do mesmo. Nesta classe temos algumas opções, como: Definir nomes, ícones, ID entre outros recursos. Ela possui como herança a classe do Tipo “Object”. Abaixo indicarei os métodos mais comuns.

Métodos

Ambos os métodos possuem 3 opções de escrita.

1-) setIndicator(): Tem como principal função especificar uma identificação para a aba.

Exemplo: 

tabSpec1.setIndicator("PessoaFisica",getResources().getDrawable(R.drawable.fisica));

No caso acima temos como primeiro parâmetro um Texto informativo e o segundo o ícone utilizado.
Outras implementações deste método:

public TabHost.TabSpec setIndicator (CharSequence label)

Utiliza como parâmetro apenas uma variável do tipo Texto.

public TabHost.TabSpec setIndicator (View view)

Neste caso apenas a View do contexto.

2-) setContent():  Em poucas palavras é através deste método que englobamos a classe da aba especificada. Passamos como parâmetro uma variável do tipo “Intent”.

Exemplo: tabSpec1.setContent(new Intent(this,AbaPessoaFisica.class));

Outras implementações deste método:

public TabHost.TabSpec setContent (int viewId)

Passamos apenas o ID para obter o retorno.

public TabHost.TabSpec setContent (TabHost.TabContentFactory contentFactory)

Já neste método de escrita devemos enviar o objeto contendo todas as informações necessárias, do tipo “TabContentFactory”.

Criando o exemplo prático

O nosso exemplo envolverá 3 Atividades, sendo: a Aba Principal onde conterá as Abas: Física e Jurídica. (“AbaPrincipal.java” , “AbaPessoaFisica.java” e “AbaPessoaJuridica.java”). Na aba invocaremos as classes acima abordadas. Montaremos no braço o layout utilizado com o auxílio da classe “LinearLayout” junto com componentes: “TextView”, “EditText” e “Button”. Para isto descreverei todos os passos daqui pra frente. Inicie uma aplicação do Zero clicando em “File/New/Android Project...” Criando as três atividades descritas acima. Ver Imagem 01.

Figura 01: Classes.

Codificando o Exemplo

1-) Classe “AbaPessoaFisica.java”

Utilizaremos algumas bibliotecas adicionais para desenvolver este exemplo, veja abaixo:
                                                                
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

É importante lembrar que ambas as abas (Pessoa Física e Pessoa Jurídica) irão herdar da classe “Activity”. Através do método “OnCreate” que iremos criar os objetos  necessários para o layout. Confiram na codificação a seguir.

public class AbaPessoaFisica extends Activity
{                                                                         
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
   
        super.onCreate(savedInstanceState);
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        linearLayout.setLayoutParams(new       LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
        linearLayout.setBackgroundColor(Color.BLUE);
        linearLayout.setPadding(12, 12, 12, 12);

O primeiro passo seria instanciar um objeto do tipo “LinearLayout”, o qual armazenaremos todos os componentes que desejarmos. O método “setOrientation()” define o layout como Vertical, o “setlayoutParams()” alguns parâmetros de configuração e o “setBackgroundColor()” a cor de fundo. Já o método “setPadding()” as margens configuradas.
       
        TextView tvNome = new TextView(this);
        tvNome.setText("Nome");
tvNome.setLayoutParams(new  LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
       
        EditText etNome = new EditText(this);
        etNome.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
               
        TextView tvCpf = new TextView(this);
        tvCpf.setText("CPF");
        tvCpf.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
       
        EditText etCpf = new EditText(this);
        etCpf.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
      
        TextView tvRg = new TextView(this);
        tvRg.setText("RG");
        tvRg.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
    
        EditText etRg = new EditText(this);
        etRg.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
       
        Button btGravar = new Button(this);
        btGravar.setText("Botão Pessoa Fisica");
        btGravar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
        btGravar.setGravity(Gravity.RIGHT);

Tanto para o TextView, EditText e Button seguimos o mesmo procedimento. Instanciamos o objeto e executamos alguns métodos referentes às configurações, como por exemplo “setText()” para adicionar rótulo no “TextView” e “Button” entre outras configurações básicas.
        
        linearLayout.addView(tvNome);
        linearLayout.addView(etNome);
        linearLayout.addView(tvCpf);
        linearLayout.addView(etCpf);
        linearLayout.addView(tvRg);
        linearLayout.addView(etRg);
        linearLayout.addView(btGravar);

Adicionamos na tela estes componentes citados no momento em que invocamos o método “addView” do “LinearLayout”.

        setContentView(linearLayout);

Ao invés de chamarmos o arquivo de layout utilizando o “.xml”, podemos fazê-lo diretamente como foi realizado no código anterior, ou seja, teremos o objeto “linearLayout” como a View responsável pela Aba de Pessoa Física.
   
}
}
Listagem 01: Aba Pessoa Física.       
Teremos o resultado na Imagem 02.
 
Figura 02: Aba Pessoa Física. 


2-) Classe “AbaPessoaJuridica.java”

O código da classe “AbaPessoaJuridica.java” seguirá os mesmos passos descritos anteriormente. Teremos algumas diferenças de configurações de cor de Fundo e nome dos campos como por exemplo do “TextView” e do “Button”. Ver Listagem 02.
                                                                        
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

public class AbaPessoaJuridica extends Activity {
                                                                         
    @Override
    public void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        linearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
        linearLayout.setBackgroundColor(Color.BLACK);
        linearLayout.setPadding(12, 12, 12, 12);
       
        TextView tvNome = new TextView(this);
        tvNome.setText("Razão Social");
        tvNome.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
       
        EditText etNome = new EditText(this);
        etNome.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
       
       
        TextView tvCpf = new TextView(this);
        tvCpf.setText("CNPJ");
        tvCpf.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
       
        EditText etCpf = new EditText(this);
        etCpf.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
       
        TextView tvIe = new TextView(this);
        tvIe.setText("IE");
        tvIe.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
    
        EditText etIe = new EditText(this);
        etIe.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
            
        Button btGravar = new Button(this);
        btGravar.setText("Gravar Pessoa Juridica");
        btGravar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
        btGravar.setGravity(Gravity.RIGHT);
       
        linearLayout.addView(tvNome);
        linearLayout.addView(etNome);
        linearLayout.addView(tvCpf);
        linearLayout.addView(etCpf);
        linearLayout.addView(tvIe);
        linearLayout.addView(etIe);
        linearLayout.addView(btGravar);
               
        setContentView(linearLayout);
    }
}
Listagem 02: Aba Pessoa Jurídica.     
                                                                  
Teremos o resultado na Imagem 03.

 
Figura 03: Aba Pessoa Jurídica. 
 
3-) Classe “AbaPrincipal.java”

Já nesta classe é onde utilizaremos as classes e métodos abordados no início do artigo. Englobaremos as classes “AbaPessoaFisica e AbaPessoaJuridica” implementadas anteriormente.
Importe os seguintes Namespaces.

import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabContentFactory;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;

Esta classe irá herdar da TabActivity e implementar as múltiplas interfaces “OnTabChangeListener e TabContentFactory”. É importante ressaltar que mesmo não utilizando os métodos “createTabContent(String tag)” e “onTabChanged(String tabId)” destas interfaces deveremos sobrescrevê-los com retornos nulos.

public class AbasPrincipal extends TabActivity implements OnTabChangeListener, TabContentFactory
{
       @Override
         public void onCreate(Bundle savedInstanceState)
         {
             super.onCreate(savedInstanceState);
            
             TabHost tabHost = getTabHost();
             tabHost.setOnTabChangedListener(this);
             TabSpec tabSpec1 = tabHost.newTabSpec("Pessoa Fisica");
             tabSpec1.setIndicator("Pessoa Fisica",getResources().getDrawable(R.drawable.fisica));
             tabSpec1.setContent(new Intent(this,AbaPessoaFisica.class));
            
             TabSpec tabSpec2 = tabHost.newTabSpec("Pessoa Juridica");
             tabSpec2.setIndicator("Pessoa Juridica",getResources().getDrawable(R.drawable.juridica));
             tabSpec2.setContent(new Intent(this,AbaPessoaJuridica.class));
      
             tabHost.addTab(tabSpec1);
             tabHost.addTab(tabSpec2);
            
       }
    
     @Override
     public View createTabContent(String tag)
     {
         return null;
     }


     @Override
     public void onTabChanged(String tabId)
     { }
}

No evento “Oncreate()” é onde estará concentrado a codificação necessária. Instanciaremos a classe “TabHost” para retornar o tabHost da atividade através do método “getTabHost()”. O método “setOnTabChangedListener()” será disparado quando qualquer um dos itens da guia é selecionado. Os dois métodos implementados na classe “Tabspec” são: o “setIndicator()” e o “setContent()” que respectivamente serve para especificar uma identificação para a aba e englobar e invocar a classe especificada. (Ambos explicados detalhadamente no início do artigo). O último passo seria adicionar as guias no objeto “TabHost” através do método “addTab()”.

Conclusões

A minha intenção neste mês foi de aprofundar um pouco mais sobre um assunto de extrema importância no desenvolvimento de sistemas, o uso de Abas. Aproveitei também para os ensinar sobre criação dinâmica de “Layouts”, ou seja, tudo foi armazenado em uma classe “.java”, diferentemente dos outros artigos que tinham como base um arquivo “.xml”. Espero que com estas dicas os ajudem a desenvolver e implementar novas funcionalidades em seus sistemas.
Um abraço e até a próxima.

Referências

http://developer.android.com/reference/android/widget/TabHost.TabSpec.html


Nenhum comentário:

Postar um comentário