segunda-feira, 22 de outubro de 2012

Context Menu em Listas no Android

Olá povo,

Estava dando aula e precisei mostrar para os meus alunos um exemplo de um menu de contexto. Mas o que é um menu de contexto? É basicamente é uma lista de opções que é exibida quando o usuário dá um clique longo em um componente da tela. Isso é particularmente útil em uma lista, onde você pode realizar várias operações sobre um determinado item.
É esse exemplo que mostraremos aqui. Crie um novo projeto, e em seguida crie o arquivo menu_contexto.xml na pasta menu (essa pasta não existe, você deve criá-la).
<menu 
  xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/opcao1" 
    android:title="Opção 1"/>
  <item android:id="@+id/opcao2" 
    android:title="Opção 2"/>
  <item android:id="@+id/opcao3" 
    android:title="Opção 3"/>
</menu>
Esse arquivo contém as opções de menu que aparecerão no menu de contexto. Carregaremos essas opções no método onCreateContextMenu na nossa Activity.
public class MainActivity extends ListActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        
    String[] nomes = {
      "Fulano", "Cicrano", "Beltrano", "João",
      "Maria", "José", "Antônio", "Francisco" };
        
    ArrayAdapter<String> adapter = 
      new ArrayAdapter<String>(this,
        android.R.layout.simple_list_item_1, nomes);
    setListAdapter(adapter);
    registerForContextMenu(getListView());
  }
    
  @Override
  public void onCreateContextMenu(ContextMenu menu, 
    View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    getMenuInflater().inflate(
      R.menu.menu_contexto, menu);
  }
    
  @Override
  public boolean onContextItemSelected(MenuItem item){
    AdapterContextMenuInfo info = 
      (AdapterContextMenuInfo)item.getMenuInfo();
     
    String nomeSelecionado = (String)
      getListView().getItemAtPosition(info.position);
     
    switch (item.getItemId()) {
    case R.id.opcao1:
      Toast.makeText(this, "Opção 1 - "+ 
        nomeSelecionado, Toast.LENGTH_SHORT).show();
      return true;
    case R.id.opcao2:
      Toast.makeText(this, "Opção 2 - "+ 
        nomeSelecionado, Toast.LENGTH_SHORT).show();
      return true;
    case R.id.opcao3:
      Toast.makeText(this, "Opção 3 - "+ 
        nomeSelecionado, Toast.LENGTH_SHORT).show();
      return true;   
    }
    return super.onContextItemSelected(item);
  }
}
A primeira etapa para criar o menu de contexto é chamar o método registerForContextMenu, passando um objeto View. Pode ser qualquer View, mas no nosso exemplo estamos pegando a ListView (que a classe ListActivity tem internamente). No método onCreateContextMenu utilizamos a classe MenuInflater para carregar o arquivo de menu que criamos anteriormente.
Por fim, para tratar as opções de menu, utilizamos o método onContextItemSelected. Esse método começa resolvendo um problema que temos quando usamos um menu de contexto em uma lista: quando o menu de contexto é aberto, perdemos o item que estava selecionado na lista.
Felizmente, podemos obter essa informação através do método getMenuInfo, que quando chamado em um item de menu que está associada a view, que é preenchida por um Adapter (a ListView está usando um ArrayAdapter para exibir seu conteúdo), retorna uma instância da classe AdapterContextMenuInfo. Nela podemos obter a linha que foi selecionada através do atributo position.
Para saber a opção de menu que foi selecionada, usamos o método getItemId, e comparamos com os ids que foram definidos no arquivo XML de menu. Abaixo temos a nossa aplicação em execução.

Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber

8 comentários:

Anônimo disse...

Bem legal!

Tony Roger disse...

Parabéns pelo seu blog! Você mostra muito conhecimento no assunto. Deveria explorar isso mais criando video-aulas, ensinando a distância pela web.

Abraço!!

Nelson Glauber de Vasconcelos Leal disse...

Valeu Tony!

Gosto muito de escrever, por isso prefiro os post às video aulas. Mas dou cursos EAD de Android e iOS (lançando em breve). Mais detalhes em:
http://www.cesar.edu.br

4br4ç05,
nglauber

Fernanda Cerqueira disse...

Queimei mufa aqui, revisando o código e tava igualzinho ao seu. Aí, reli o texto e vi: longo clique.. Não tem como fazer isso para um clique normal?

Obrigada.

Nelson Glauber de Vasconcelos Leal disse...

Oi Fernanda,

Aí você pode usar um Dialog normal.
http://developer.android.com/guide/topics/ui/dialogs.html#AddingAList

4br4ç05,
nglauber

Alessandro Ferreira Antonio disse...

Tem como colocar imagens no menu?

Nelson Glauber disse...

Oi Alessando,

O menu de contexto não suporta ícones. Mas você pode usar esse componente aqui:
https://code.google.com/p/android-icon-context-menu/

Entrentanto aconselho você usar o menu de contexto da ActionBar que eu mostrei nesse post aqui:
http://nglauber.blogspot.com.br/2013/07/listview-com-selecao-multipla-actionbar.html

4br4ç05,
nglauber

Anônimo disse...

Ótima explicação! obrigado!! parabéns
Rubens