Exibindo uma Activity no Android

No sistema operacional do Android as telas que são apresentadas para o usuário são chamadas de Activity. Este post demonstra como chamar uma Activity “filha” através de uma Activity “pai” e retornar uma resposta quando o usuário retorna para a Activity “pai”.

Para demonstrar a chamada da Activity foi utilizado o mesmo projeto do post Criando um ListAdapter Customizado para o ListView do Android como projeto de partida. No projeto foi criado um ListView que exibe as informações dos Estados do Brasil.

Neste post será implementada a chamada de uma Activity “filha” para exibir os detalhes do Estado que foi selecionado pelo usuário. Na Figura 1 temos a Activity principal que exibe a relação de Estados do Brasil, juntamente com as informações da Capital e Área do Estado. Na Figura 2 temos a Activity “filha” que exibe os detalhes do Estado selecionado pelo usuário. No exemplo o Estado selecionado foi Rio Grande do Norte.

figura_1_2
Para exibir a Activity “filha” foi necessário fazer algumas inserções no código do projeto de partida, demonstrado na Listagem 1:

Listagem 1:
   1:  package br.com.romar;
   2:   
   3:  import java.util.ArrayList;
   4:  import java.util.List;
   5:   
   6:  import android.app.ListActivity;
   7:  import android.content.Intent;
   8:  import android.os.Bundle;
   9:  import android.view.View;
  10:  import android.widget.AdapterView;
  11:  import android.widget.ListView;
  12:  import android.widget.AdapterView.OnItemClickListener;
  13:   
  14:  public class Main extends ListActivity implements OnItemClickListener {
  15:      List<State> stateList;
  16:      
  17:      /** Called when the activity is first created. */
  18:      @Override
  19:      public void onCreate(Bundle savedInstanceState) {
  20:          super.onCreate(savedInstanceState);
  21:          
  22:          stateList = new ArrayList<State>();
  23:          
  24:          for (int i = 0; i < states.length; i++) {
  25:              State state = new State();
  26:              state.setState(states[i][0]);
  27:              state.setAbbreviation(states[i][1]);
  28:              state.setCapital(states[i][2]);
  29:              state.setArea(Float.parseFloat(states[i][3]));
  30:              state.setBanner(images[i]);
  31:              
  32:              stateList.add(state);
  33:          }  
  34:          
  35:          setListAdapter(new StateAdapter(this, stateList));
  36:          
  37:          ListView listview = getListView();
  38:          
  39:          listview.setOnItemClickListener(this);
  40:      }
  41:      
  42:      @Override
  43:      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  44:          
  45:          // Obtêm os detalhes do Estado selecionado
  46:          State state = stateList.get(position);
  47:          
  48:          // Exibe a Activity com os detalhes dos Estados
  49:          Intent intent = new Intent(this, DetailActivity.class);
  50:          Bundle params = new Bundle();
  51:          params.putString("estado", state.getState());
  52:          params.putString("capital", state.getCapital());
  53:          params.putFloat("area", state.getArea());
  54:          intent.putExtras(params);
  55:          
  56:          startActivity(intent);
  57:      }
  58:   
  59:      
  60:      private String[][] states = new String[][]{
  61:             {"Acre", "AC", "Rio Branco", "152581.4"},
  62:             {"Alagoas", "AL", "Maceió", "27767.7"},
  63:             {"Amapá", "AP", "Macapá", "142814.6"},
  64:             {"Amazonas", "AM", "Manaus", "1570745.7"},
  65:             {"Bahia", "BA", "Salvador", "564692.7"},
  66:             {"Ceará", "CE", "Fortaleza", "148825.6"},
  67:             {"Distrito Federal", "DF", "Brasília", "5822.1"},
  68:             {"Espírito Santo", "ES", "Vitória", "46077.5"},
  69:             {"Goiás", "GO", "Goiânia", "340086.7"},
  70:             {"Maranhão", "MA", "São Luís", "331983.3"},
  71:             {"Mato Grosso", "MT", "Cuiabá", "903357.9"},
  72:             {"Mato Grosso do Sul", "MS", "Campo Grande", "357125.0"},
  73:             {"Minas Gerais", "MG", "Belo Horizonte", "586528.3"},
  74:             {"Pará", "PA", "Belém", "1247689.5"},
  75:             {"Paraíba", "PB", "João Pessoa", "56439.8"},
  76:             {"Paraná", "PR", "Curitiba", "199314.9"},
  77:             {"Pernambuco", "PE", "Recife", "98311.6"},
  78:             {"Piauí", "PI", "Teresina", "251529.2"},
  79:             {"Rio de Janeiro", "RJ", "Rio de Janeiro", "43696.1"},
  80:             {"Rio Grande do Norte", "RN", "Natal", "52796.8"},
  81:             {"Rio Grande do Sul", "RS", "Porto Alegre", "281748.5"},
  82:             {"Rondônia", "RO", "Porto Velho", "237576.2"},
  83:             {"Roraima", "RR", "Boa Vista", "224299.0"},
  84:             {"Santa Catarina", "SC", "Florianópolis", "95346.2"},
  85:             {"São Paulo", "SP", "São Paulo", "248209.4"},
  86:             {"Sergipe", "SE", "Aracaju", "21910.3"},
  87:             {"Tocantins", "TO", "Palmas", "277620.9"}
  88:         };
  89:      
  90:      private int[] images = new int[]{
  91:              R.drawable.acre,
  92:              R.drawable.alagoas,
  93:              R.drawable.amapa,
  94:              R.drawable.amazonas,
  95:              R.drawable.bahia,
  96:              R.drawable.ceara,
  97:              R.drawable.distritofederal,
  98:              R.drawable.espiritosanto,
  99:              R.drawable.goias,
 100:              R.drawable.maranhao,
 101:              R.drawable.matogrosso,
 102:              R.drawable.matogrossosul,
 103:              R.drawable.minasgerais,
 104:              R.drawable.para,
 105:              R.drawable.paraiba,
 106:              R.drawable.parana,
 107:              R.drawable.pernambuco,
 108:              R.drawable.piaui,
 109:              R.drawable.riojaneiro,
 110:              R.drawable.riograndenorte,
 111:              R.drawable.riograndesul,
 112:              R.drawable.rondonia,
 113:              R.drawable.roraima,
 114:              R.drawable.santacatarina,
 115:              R.drawable.saopaulo,
 116:              R.drawable.sergipe,
 117:              R.drawable.tocatins
 118:      };
 119:   
 120:  }

Na linha 14 foi implementada a interface OnItemClickListener.

Na linha 37 foi obtido o widget ListView da Activity através do método getListView().

Na linha 39 foi registrado um callback para ser chamado quando um item no AdapterView é clicado, através do método setOnItemClickListener(AdapterView.OnItemClick listener).

Nas linhas 42 a 57 é sobrescrito o método onItemClick(AdapterView<?> parent, View view, int position, long id), que obtêm o Estado selecionado e as informações a serem exibidas na segunda Activity. Através do método startActivity(Intent) a Activity da Figura 2 é exibida.

Nas linhas 49 a 54 é criado o objeto intent e o objeto params onde são definidas as informações que serão passadas para a Activity “filha”.

Para que seja exibida a Activity “filha” (chamada de DetailActivity) não esquecer de declarar a Activity  no arquivo AndroidManifest.xml do projeto.
        <activity android:name=".DetailActivity" android:label="Detalhes do Estado"/>
No arquivo da Activity DetailActivity no método OnCreate(Bundle savedInstanceState) são obtidos os valores das informações passadas pela Activity “pai”, demonstrado na Listagem 2.

Listagem 2:
   1:      @Override
   2:      protected void onCreate(Bundle savedInstanceState) {
   3:          super.onCreate(savedInstanceState);
   4:          
   5:          // Configura o layout da Activity
   6:          setContentView(R.layout.state_detail);
   7:          
   8:          // Widgets da Activity
   9:          TextView textEstado = (TextView)findViewById(R.id.textEstado);
  10:          TextView textCapital = (TextView)findViewById(R.id.textCapital);
  11:          TextView textArea = (TextView)findViewById(R.id.textArea);
  12:          
  13:          // Carrega os valores passados pela Activity Principal (Main)
  14:          Intent intent = getIntent();
  15:          
  16:          if (intent != null) {
  17:              textEstado.setText(intent.getStringExtra("estado"));
  18:              textCapital.setText(intent.getStringExtra("capital"));
  19:              textArea.setText(String.valueOf(intent.getFloatExtra("area", 0)));            
  20:          }
  21:      }

Na linha 14 as informações passadas pela Activity “pai” são obtidas através do método getIntent().
Agora, e se com a apresentação da Activity “filha” quisessemos preencher algum campo e retornar esta informação para a Activity “pai”? Isto pode ser feito utilizando-se o método startActivityForResult(Intent, int) ao invés do método startActivity(Intent) utilizado anteriormente.

O método startActivityForResult(Intent, int)  faz a chamada de outra Activity, só que desta vez além do parâmetro Intent é passado como parâmetro um número inteiro utilizado para identificar a chamada.O resultado retornará através do método onActivityResult(int, int, Intent).

Quando saímos de uma Activity, ela pode chamar o método setResult(int) para retornar um dado de volta para a Activity chamadora. A Activity deve fornecer um código, que pode ser os resultados padrão RESULT_CANCELED, RESULT_OK, ou qualquer valor customizado. Opcionalmente ela pode retornar um Intent contendo dados adicionais.

Para demonstrar como retornar dados de uma Activity “filha”, vou utilizar o mesmo projeto fazendo pequenas alterações.

Na classe Main exibida na Listagem 1 acima, incluir a declaração da seguinte constante na classe.
private final static int CALL_SECOND_ACTIVITY = 1;

Esta constante define o valor de identificação a ser passado no segundo parâmetro do método startActivityForResult(Intent, int).

No método onItemClick(AdapterView<?> parent, View view, int position, long id) demonstrado na linha 43 da Listagem 1, substituir a chamada da Activity startActivity(Intent) (linha 56) pela linha abaixo:

startActivityForResult(intent,CALL_SECOND_ACTIVITY);




No código da Listagem 1 incluir o método onActivityResult(int, int, Intent), conforme demonstrado abaixo na Listagem 3:

Listagem 3:
   1:      /**
   2:       * Método chamado quando saímos da DetailActivity
   3:       * @param requestCode O código inteiro originalmente fornecido
   4:       * no método startActivityForResult(), permitindo identificar
   5:       * quem fez a chamada.
   6:       * @param resultCode O código inteiro retornado pela Activity
   7:       * filha através do método setResult().
   8:       * @param data Um Intent que pode retornar dados ao chamador.
   9:       */
  10:      @Override
  11:      protected void onActivityResult(int requestCode, 
  12:              int resultCode, Intent data) {
  13:          super.onActivityResult(requestCode, resultCode, data);
  14:          
  15:          // Verifica se é o código de quem fez a chamada
  16:          if (requestCode == CALL_SECOND_ACTIVITY) {
  17:              // Verifica se o retorno foi com sucesso
  18:              if (resultCode ==RESULT_OK) {
  19:                  if (data != null) {
  20:                      Bundle params = data.getExtras();
  21:                      if (params.getBoolean("visitar") == true) {
  22:                           Toast.makeText(this, "Quero visitar " + 
  23:                                   params.getString("estado"), 
  24:                                   Toast.LENGTH_SHORT).show();
  25:                      }
  26:                  }
  27:              }
  28:          }
  29:      }

Este método será chamado quando a Activity “filha” for fechada.
Na linha 16 é verificado se o código da identificação representa o mesmo código passado na chamada.

Na linha 21 através da classe Bundle obtemos a informação se o usuário deseja visitar o Estado e o nome do Estado.

Substituir o código da Listagem 2 pelo da Listagem 4:
Listagem 4:
   1:  public class DetailActivity extends Activity implements OnClickListener {
   2:      TextView textEstado;
   3:      TextView textCapital;
   4:      TextView textArea;
   5:      
   6:      @Override
   7:      protected void onCreate(Bundle savedInstanceState) {
   8:          super.onCreate(savedInstanceState);
   9:          
  10:          // Configura o layout da Activity
  11:          setContentView(R.layout.state_detail);
  12:          
  13:          // Widgets da Activity
  14:          textEstado = (TextView)findViewById(R.id.textEstado);
  15:          textCapital = (TextView)findViewById(R.id.textCapital);
  16:          textArea = (TextView)findViewById(R.id.textArea);
  17:          
  18:          // Carrega os valores passados pela Activity Principal (Main)
  19:          Intent intent = getIntent();
  20:          
  21:          if (intent != null) {
  22:              textEstado.setText(intent.getStringExtra("estado"));
  23:              textCapital.setText(intent.getStringExtra("capital"));
  24:              textArea.setText(String.valueOf(intent.getFloatExtra("area", 0)));            
  25:          }
  26:          
  27:          final RadioButton rbSim = (RadioButton)findViewById(R.id.rbSim);
  28:          final RadioButton rbNao = (RadioButton)findViewById(R.id.rbNao);
  29:          
  30:          rbSim.setOnClickListener(this);
  31:          rbNao.setOnClickListener(this);
  32:      }
  33:   
  34:      @Override
  35:      public void onClick(View v) {
  36:          Intent intent = new Intent();        
  37:          // Verifica qual radiobutton foi selecionado
  38:          if (v.getId() == R.id.rbSim) {            
  39:              intent.putExtra("visitar", true);
  40:              intent.putExtra("estado", textEstado.getText().toString());
  41:              setResult(RESULT_OK, intent);
  42:          }
  43:      }
  44:  }

Nas linhas 27 e 28 foram incluídas as declarações do botões RadioButton.
Nas linhas 30 3 31 foram registrados os eventos OnClickListener(View.OnClickListener) para os botões Sim e Não.

A partir da linha 35 temos o método que trata o botão selecionado.  Através de um Intent, é passado um boolean informando se deseja visitar o Estado e uma String com o nome do Estado.

Na linha 41 é utilizado o método setResult(int, Intent), para poder passar o resultado OK da operação e a Intent com as informações se deseja visitar, e o nome do Estado.

Executando a aplicação com as alterações descritas e selecionando o Estado Rio Grande do Norte com a opção de visitar, quando fechamos a Activity “filha” será apresentada uma mensagem com o nome do Estado que se deseja visitar, como apresentado na Figura 3:

figura3
Atualizado: Como comentado por um leitor do post ficou faltando o xml da Activity dos detalhes do estado, que segue abaixo:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:stretchColumns="2"
  android:padding="5dp"
  >
  
  <TableRow>
      <TextView
          android:layout_column="1" 
          android:text="Estado:" 
          android:padding="3dp"
          android:textSize="24sp"
       />
      <TextView
          android:layout_column="2" 
          android:hint="Nome do Estado..." 
          android:id="@+id/textEstado"
          android:textSize="24sp"
       />       
  </TableRow>
  
  <TableRow>
      <TextView
          android:layout_column="1" 
          android:text="Capital:" 
           android:textSize="24sp"
       />
      <TextView
          android:layout_column="2" 
          android:hint="Nome da Capital..." 
          android:id="@+id/textCapital"
          android:textSize="24sp"
       />       
  </TableRow>
  
  <TableRow>
      <TextView
          android:layout_column="1" 
          android:text="Área:"
           android:textSize="24sp"
       />
      <TextView
          android:layout_column="2" 
          android:hint="Area em Km2..." 
          android:id="@+id/textArea"
           android:textSize="24sp"
       />       
  </TableRow>
  
  <TableRow>
      <TextView
          android:layout_column="1" 
          android:text="Visitar?"
           android:textSize="24sp"
       />
    <RadioGroup
        android:orientation="horizontal"
    >
        <RadioButton
            android:id="@+id/rbSim" 
            android:text="Sim"
            android:layout_height="35dp"
              android:textSize="24sp"
        />
        <RadioButton 
            android:id="@+id/rbNao" 
            android:text="Não"
            android:layout_height="35dp"
              android:textSize="24sp"
        />        
    </RadioGroup>
  </TableRow>
      
</TableLayout>