Criando menu de contexto no Android (Context Menu)

(Última atualização em: 5 de setembro de 2016)

Na App que estou desenvolvendo para armazenar meus cursos realizados na Alura, fiz uma lista de cursos e listei alguns que realizei:

tela_inicial_app_meus_curso_7

Observe que a cada vez que tocamos em um curso, ou seja, um item da lista, vamos direto para o link do curso. Porém, notei que o curso de MySQL eu ainda não concluí, ou seja, preciso deletar ele da lista. Como podemos fazer isso no Android?

Geralmente adicionamos um click listener para implementar um clique com uma ação desejada, como por exemplo, deletar o item da lista, mas, cada item da lista já contém listener de clique para acessar a URL do curso, ou seja, não faz sentido implementar um outro click listener sendo que já existe um.

Então qual é a nossa alternativa? Lembra que nos computadores temos o botão direito? Isso mesmo! Aquele botão que clicamos e ele nos da opções que podemos fazer.

Então, no Android temos algo muito similar ao botão direito que é o menu de contexto ou, tecnicamente, context menu. Mas como podemos implementá-lo?

Atualmente, na minha App, tenho a activity CursosActivity:

public class CursosActivity extends AppCompatActivity {

    private ListView cursos;
    private List<Curso> listaDeCursos;
    private CursoAdapter adapter;

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_cursos);
        cursos = (ListView) findViewById(R.id.activity_cursos_lista);
        listaDeCursos = pedeLista();
        adapter = new CursoAdapter(this, listaDeCursos);
    }

    @Override
    protected void onResume() {
        super.onResume();
        cursos.setAdapter(adapter);

        clickDaListView();
    }

    private void clickDaListView() {
        //implementação do click da lista
    }

    private List<Curso> pedeLista() {
        //faz uma pesquisa e retorna uma lista de cursos
    }

}

A partir do objeto cursos do tipo ListView, podemos chamar o método setOnCreateContextMenuListener() que nos permite criar um context menu para a ListView:

@Override
protected void onResume() {
    super.onResume();
    cursos.setAdapter(adapter);

    cursos.setOnCreateContextMenuListener();

    clickDaListView();
}

Porém, da mesma forma como vemos nos demais listener do Android, precisamos implementar a interface View.OnCreateContextMenuListener(). Portanto, faremos a implementação utilizando o recurso de classe anônima:

cursos.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
    @Override
    public void onCreateContextMenu(ContextMenu contextMenu, View view, 
ContextMenu.ContextMenuInfo contextMenuInfo) {
    }
});

A partir do parâmetro contextMenu podemos criar opções para o nosso context menu utilizando o método add:

cursos.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
    @Override
    public void onCreateContextMenu(ContextMenu contextMenu, View view, 
ContextMenu.ContextMenuInfo contextMenuInfo) {
        contextMenu.add(Menu.NONE, 1, Menu.NONE, "deletar");
    }
});

Note que enviamos 4 parâmetros:

  • 1º parâmetro: Refere-se ao groupId.
  • 2º parâmetro: Nesse parâmetro enviamos o ItemId que é justamente o id do menu, ou seja, é por meio dele que identificaremos esse menu.
  • 3º parâmetro: Nele informamos o order, ou seja, a posição que queremos ordenar o menu.
  • 4º parâmetro: Indica o nome que será exibido para o menu.

Note que tanto no groupId quanto no order colocamos o valor Menu.NONE. Essa constante equivale a 0 e significa que não queremos atribuir esses parâmetros. Em outras palavras, no código acima, criamos um menu com id 1 e nome "deletar". Vamos testá-lo?

Se rodarmos a nossa App, a princípio, nada mudou. Mas, se pressionarmos um item da lista:

menu_deletar

Veja que o nosso menu aparece! O que acontece se tocarmos no menu? Nada! Afinal, não configuramos uma ação pra ele, certo? Faremos isso então! Porém, como podemos dar uma ação para um context menu? Simples! Basta sobrescrevemos o método onContextItemSelected na CursosActivity:

@Override
public boolean onContextItemSelected(MenuItem item) {
    return super.onContextItemSelected(item);
}

Observe que ele já nos retorna o valor super.onContextItemSelected(item) que equivale ao valor true. Mas o que isso significa? Quando retornamos true, informamos que o click para esse menu, será consumido apenas por ele.

Qual é o nosso próximo passo? Precisamos verificar se a opção “deletar” foi escolhida, porém, como podemos fazer isso? O parâmetro item corresponde ao item que foi clicado, ou seja, a partir dele podemos verificar o id e, se for igual a 1, saberemos que é o menu deletar.

Podemos utilizar ifs e elses, porém, já que sabemos o que esperamos, isto é, o id 1, utilizaremos o switch case:

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case 1:
    }
    return super.onContextItemSelected(item);
}

Agora precisamos implementar a funcionalidade para deletar o curso. Porém, qual curso deletaremos? Em outras palavras, precisamos pegar primeiro a posição do curso que queremos deletar. Para pegarmos informações do item que chamou o context menu, precisamos utilizar o método getMenuInfo() do objeto item:

@Override
public boolean onContextItemSelected(MenuItem item) {
    item.getMenuInfo();
    
    //restante do código
}    

Então atribuímos o retorno desse método para um objeto do tipo AdapterView.AdapterContextMenuInfo:

@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo menuInfo = 
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    
    //restante do código
}    

A partir do objeto menuInfo podemos pegar a posição do item que chamou o context menu por meio do atributo position:

@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo menuInfo = 
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    int position = menuInfo.position;

    //restante do código
}    

Agora que temos a posição desejada, podemos deletar o curso! Porém, antes de implementar o código, criaremos o método deletar() enviando a position:

@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterView.AdapterContextMenuInfo menuInfo = 
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    int position = menuInfo.position;
    switch (item.getItemId()) {
        case 1:
            deletar(position);
        }
        return super.onContextItemSelected(item);
}

private void deletar(int position) {
}

Para deletar um item da lista, basta apenas usarmos o remove() da listaDeCursos enviando a position:

listaDeCursos.remove(position);

E então, notificamos o adapter dizendo que a lista foi modificada por meio do método notifyDataSetChanged():

private void deletar(int position) {
        listaDeCursos.remove(position);
        adapter.notifyDataSetChanged();
}

Vamos testar o nosso código? Vejamos o resultado:

deletando_item

O curso de MySQL é deletado conforme o esperado!

Nesse post vimos o “botão direito” do Android, ou seja, o context menu. Implementamos dentro de uma ListView e vimos que, por padrão, ele funciona a partir de um click longo, ou melhor, pressionando o item da lista. Por fim, vimos como podemos adicionar ações para cada item do context menu buscando pelo seu id.

Já conhecia o context menu? Não? O que achou dele? Deixe seu comentário 🙂

Que tal aprender a desenvolver a sua App Android desde o zero? Aqui na Alura, temos diversos cursos online de Android onde ensinamos você a desenvolver a sua primeira App com os principais conceitos do início ao fim.

Content Editor at Alura and Software Developer

  • Carlos Henrique dos Santos Lim

    Nesse metodo vc pode me da uma dica de como ficaria a implementação pq estou quebrando a cabeça e não consigo…
    Vc colocou um comentario: ( //faz uma pesquisa e retorna uma lista de cursos) , entao devo criar uma classe com CRUD ?

    private List pedeLista() {
    //codigo
    }

    • Alex Felipe

      Oi Carlos, tudo bem? Basicamente é isso mesmo, nesse tipo de método normalmente fazemos uma busca na nossa base de dados, ou seja, esse método poderia ser responsável em consultar a base de dados da sua aplicação, pegar todos os cursos e devolver uma lista dos mesmos, é claro, considerando esse contexto.

      Como teste, você pode simplesmente fazer uma instância de lista de cursos manualmente mesmo. 🙂

  • Pingback: Blog da Alura: desenvolvimento, design e muita tecnologia – Criando caixas de diálogo no Android (Dialogs)()

Próximo ArtigoCarreira em Marketing Digital: por onde começar?