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.
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:
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>