A Figura 4.21 declara e inicializa a variável de instância saveButtonListener, a qual faz
referência a um objeto de classe interna anônima que implementa a interface OnClickLis- tener. A linha 64 (Fig. 4.20) registrou saveButtonListener como rotina de tratamento
de eventos de saveButton. As linhas 76 a 109 sobrescrevem o método onClick da inter-
face OnClickListener. Se o usuário digitou uma consulta e um identificador (linhas 80 e
81), as linhas 83 e 84 chamam o método addTaggedSearch (Fig. 4.23) para armazenar o
par identificador-consulta e as linhas 85 e 86 limpam os dois componentes EditText. As
73 // saveButtonListener salva um par identificador-consulta em SharedPreferences 74 public OnClickListener saveButtonListener = new OnClickListener()
75 {
76 @Override
77 public void onClick(View v)
78 {
79 // cria identificador se nem queryEditText nem tagEditText está vazio 80 if (queryEditText.getText().length() > 0 &&
81 tagEditText.getText().length() > 0)
82 {
83 addTaggedSearch(queryEditText.getText().toString(),
84 tagEditText.getText().toString());
85 queryEditText.setText("");// limpa queryEditText 86 tagEditText.setText(""); // limpa tagEditText 87
88
89
90
91 }
92 else // exibe mensagem solicitando que forneça uma consulta e um identificador 93 { 94 95 96 97 98 99 100 101 102 103 104 105 106 107 }
108 } // fim do método onClick
109 }; // fim da classe interna anônima OnClickListener 110
((InputMethodManager) getSystemService( Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow( tagEditText.getWindowToken(), 0);
// cria um novo AlertDialog Builder
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
// configura o título da caixa de diálogo e a mensagem a ser exibida
builder.setMessage(R.string.missingMessage);
// fornece um botão OK que simplesmente remove a caixa de diálogo
builder.setPositiveButton(R.string.OK, null);
// cria AlertDialog a partir de AlertDialog.Builder
AlertDialog errorDialog = builder.create(); errorDialog.show(); // exibe a caixa de diálogo modal
Figura 4.21 Classe interna anônima que implementa a interface OnClickListener de saveButton para salvar uma pesquisa nova ou atualizada.
Configurando um componente AlertDialog
Se o usuário não digitou uma consulta e um identificador, as linhas 92 a 108 exibem um elemento AlertDialog indicando que ele deve digitar ambos. Um objeto AlertDialog.Buil- der (linhas 95 e 96) ajuda a configurar e criar um componente AlertDialog. O argumento
do construtor é o objeto Context no qual a caixa de diálogo vai ser exibida – neste caso, o
elemento MainActivity, ao qual nos referimos por meio de sua referência this. Para acessar this a partir de uma classe interna anônima, você deve qualificá-lo totalmente com o nome
da classe externa. A linha 99 configura a mensagem da caixa de diálogo com o recurso
String R.string.missingMessage ("Enter both a Twitter search query and a tag").
Observação sobre aparência e comportamento 4.5
É possível configurar o título de AlertDialog (o qual aparece acima da mensagem da
caixa de diálogo) com o método setTitle de AlertDialog.Builder. De acordo com as
diretrizes de projeto do Android para caixas de diálogo (http://developer.android.com/ design/building-blocks/dialogs.html), a maioria delas não precisa de títulos. Uma cai-
xa de diálogo deve exibir um título para “uma operação de alto risco, envolvendo possível perda de dados, conectividade, cobranças extras e assim por diante”. Além disso, as caixas de diálogo que exibem listas de opções utilizam o título para especificar sua finalidade.
Adicionando recursos de String a strings.xml
Para criar recursos de String, como R.string.missingMessage, abra o arquivo strings. xml, localizado na pasta res/values do projeto. O IDE mostra esse arquivo em um editor
de recursos que tem duas guias – Resources e strings.xml. Na caixa de diálogo Resources,
clique em Add... para exibir a caixa de diálogo da Fig. 4.22. Selecionar String e clicar em OK exibe os campos de texto Name e Value, em que você pode digitar um novo nome (por
exemplo, missingMessage) e um novo valor de recurso String. Salve seu arquivo strings. xml após fazer as alterações. Você também pode usar a guia Resource do editor de recursos
para selecionar um recurso String já existente a fim de alterar seu nome e valor.
Figura 4.22 Adicionando um recurso de String.
Especificando o botão positivo do componente AlertDialog
Neste componente AlertDialog, precisamos de apenas um botão que permita ao usuário
aceitar a mensagem. Especificamos isso como o botão positivo da caixa de diálogo (Fig. 4.21, linha 102) – tocar nesse botão indica que o usuário aceita a mensagem exibida na caixa de diálogo. O método setPositiveButton recebe o rótulo do botão (especificado
com o recurso de String R.string.OK) e uma referência para a rotina de tratamento de
eventos do botão. Para essa caixa de diálogo não precisamos responder ao evento; por- tanto, especificamos null para a rotina de tratamento de eventos. Quando o usuário toca
no botão, a caixa de diálogo simplesmente desaparece da tela. Criação e exibição do componente AlertDialog
Você cria o componente AlertDialog chamando o método create de AlertDialog.Buil- der (linha 105) e exibe a caixa de diálogo modal chamando o método show de AlertDia- log (linha 106).
4.5.6 Método
addTaggedSearchA rotina de tratamento de eventos da Fig. 4.21 chama o método addTaggedSearch de MainActivity (Fig. 4.23) para adicionar uma nova pesquisa a savedSearches ou para
111 // adiciona uma nova pesquisa ao arquivo de salvamento e, então, atualiza todos
// os componentes Button
112 private void addTaggedSearch(String query, String tag)
113 { 114 115 116 117 118
119 // se o identificador é novo, adiciona-o, ordena tags e exibe a lista atualizada 120 if (!tags.contains(tag))
121 {
122 tags.add(tag); // adiciona o novo identificador 123 Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
124
125 }
126 }
127
// obtém um objeto SharedPreferences.Editor para armazenar novos pares // identificador-consulta
SharedPreferences.Editor preferencesEditor = savedSearches.edit(); preferencesEditor.putString(tag, query); // armazena pesquisa atual
preferencesEditor.apply(); // armazena as preferências atualizadas
adapter.notifyDataSetChanged(); // vincula os identificadores a ListView
Figura 4.23 Método addTaggedSearch da classe MainActivity.
Editando o conteúdo de um objeto SharedPreferences
Para alterar o conteúdo de um objeto SharedPreferences, você deve primeiramente
chamar seu método edit a fim de obter um objeto SharedPreferences.Editor (linha
115), o qual pode adicionar e remover pares chave-valor e modificar o valor associado a uma chave específica em um arquivo SharedPreferences. A linha 116 chama o método
putString de SharedPreferences.Editor para salvar o identificador da pesquisa (a chave)
e a consulta (o valor correspondente) – caso o identificador já exista no objeto Shared- Preferences, isso atualiza o valor. A linha 117 efetiva as alterações, chamando o método
apply de SharedPreferences.Editor para fazer as mudanças no arquivo.
Notificando o componente ArrayAdapter de que seus dados mudaram Quando o usuário adiciona uma nova pesquisa, o componente ListView deve ser atuali-
zado para exibi-la. As linhas 120 a 125 determinam se um novo identificador foi adicio- nado. Em caso positivo, as linhas 122 e 123 adicionam o identificador da nova pesquisa a tags e, então, ordenam a coleção. A linha 124 chama o método notifyDataSetChanged de ArrayAdapter para indicar que os dados subjacentes em tags foram alterados. Então,
o adaptador notifica o componente ListView para que atualize sua lista de itens exibidos.
4.5.7 Classe interna anônima que implementa a interface
OnItemClickListener
de
ListViewpara exibir resultados de
pesquisa
A Figura 4.24 declara e inicializa a variável de instância itemClickListener, a qual faz
referência a um objeto de classe interna anônima que implementa a interface OnItemCli- ckListener. A linha 67 (Fig. 4.20) registrou itemClickListener como a rotina de trata-
mento de eventos de ListView que responde quando o usuário toca em um item no com-
ponente ListView. As linhas 131 a 145 sobrescrevem o método onItemClick da interface OnItemClickListener. Os argumentos do método são:
• O elemento AdapterView em que o usuário tocou em um item. O ? em Adapter- View<?> é um curinga nos tipos genéricos Java indicando que o método onItemCli- ck pode receber um objeto AdapterView que exibe qualquer tipo de dado – neste
• O elemento View em que o usuário tocou no objeto AdapterView – neste caso, o
componente TextView que exibe o identificador de uma busca.
• O número do índice, com base zero, do item em que o usuário tocou.
• O identificador da linha do item que foi tocado – isso é usado principalmente para dados obtidos de um banco de dados (como você vai fazer no Capítulo 8).
128 // itemClickListener ativa o navegador Web para exibir resultados da busca 129 OnItemClickListener itemClickListener = new OnItemClickListener()
130 {
131 @Override
132 public void onItemClick(AdapterView<?> parent, View view,
133 int position, long id)
134 {
135 // obtém a string de consulta e cria uma URL representando a busca 136 String tag = ((TextView) view).getText().toString();
137 String urlString = + 138 ; 139 140 141 142 143 144 145 }
146 }; // fim da declaração de itemClickListener 147
getString(R.string.searchURL)
Uri.encode(savedSearches.getString(tag, ""), "UTF-8")
// cria um objeto Intent para ativar um navegador Web
Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlString));
startActivity(webIntent); // ativa o navegador Web para ver os resultados
Figura 4.24 Classe interna anônima que implementa a interface OnItemClickListener de ListView para exibir os resultados da pesquisa.
Obtendo recursos de String
A linha 136 obtém o texto do elemento View em que o usuário tocou no componente ListView. As linhas 137 e 138 criam um objeto String contendo a URL de busca no
Twitter e a consulta a ser feita. Primeiramente, a linha 137 chama o método getString herdado de Activity com apenas um argumento para obter o recurso String chamado searchURL, o qual contém a URL da página de busca do Twitter:
http://mobile.twitter.com/search/
Como em todos os recursos de String neste aplicativo, você deve adicionar esse recurso
a strings.xml.
Obtendo objetos String a partir de um objeto SharedPreferences
Anexamos o resultado da linha 138 à URL de busca para completar o objeto urlString.
O método getString de SharedPreferences retorna a consulta associada ao identificador.
Se o identificador ainda não existe, o segundo argumento ("", neste caso) é retornado. A
linha 138 passa a consulta para o método encode de Uri, o qual faz o escape de quaisquer
caracteres de URL especiais (como ?, /, :, etc.) e retorna o assim chamado objeto String
codificado em URL. Isso é importante para garantir que o servidor Web do Twitter que recebe o pedido possa analisar a URL adequadamente para obter a consulta de busca. Criando um objeto Intent para ativar o navegador Web do dispositivo As linhas 141 e 142 criam um novo objeto Intent, o qual vamos usar para ativar o
navegador Web do dispositivo e exibir os resultados da busca. Os objetos Intent podem
ser usados para ativar outras atividades no mesmo aplicativo ou em outros aplicativos. O primeiro argumento do construtor do objeto Intent é uma constante descrevendo a
ação a ser executada. Intent.ACTION_VIEW indica que queremos exibir uma representa- ção dos dados. Na classe Intent são definidas muitas constantes que descrevem ações
como pesquisar, escolher, enviar e reproduzir. O segundo argumento (linha 142) é um
Uri (uniform resource identifier) representando os dados nos quais queremos executar a ação. O método parse da classe Uri converte um objeto String representando uma URL
(uniform resource locator) em um Uri.
Iniciando uma atividade para um objeto Intent
A linha 144 passa o objeto Intent para o método herdado startActivity de Activity,
o qual inicia uma atividade que pode executar a ação especificada nos dados fornecidos. Neste caso, como especificamos a visualização de um URI, o objeto Intent ativa o nave- gador Web do dispositivo para exibir a página Web correspondente. Essa página mostra os resultados da busca fornecida no Twitter.
4.5.8 Classe interna anônima que implementa a interface
OnItemLongClickListener