39

How do you implement a context menu triggered by a long click or tap on a ListActivity that is using the built in layouts and a ListAdapter?

Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • 3
    Your edit has effectively changed the question entirely. Would probably have been better of just asking the different question. – Reto Meier Jan 14 '09 at 20:25

3 Answers3

74

On the onCreate method call registerForContextMenu like this:

registerForContextMenu(getListView());

and then populate the menu on onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo). The menuInfo argument can provide information about which item was long-clicked in this way:

AdapterView.AdapterContextMenuInfo info;
try {
    info = (AdapterView.AdapterContextMenuInfo) menuInfo;
} catch (ClassCastException e) {
    Log.e(TAG, "bad menuInfo", e);
    return;
}
long id = getListAdapter().getItemId(info.position);

and you add menu items in the usual way calling menu.add:

menu.add(0, MENU_ITEM_ID, 0, R.string.menu_string);

and when the user picks an option, onContextItemSelected is called. Also onMenuItemSelected and this fact is not explicitly explained in the documentation except to say that you use the other method to receive the calls from the context menu; just be aware, don't share ids.

On onContextItemSelected you can get ahold of the MenuInfo and thus the id of the item selected by calling getMenuInfo():

try {
    info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
} catch (ClassCastException e) {
    Log.e(TAG, "bad menuInfo", e);
    return false;
}
long id = getListAdapter().getItemId(info.position);
Mac_Cain13
  • 3,611
  • 2
  • 24
  • 38
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
  • 1
    Ahh, thanks. Been looking for that all over the Web but could only find old version. This one works perfect with cupcake. – Bite code Apr 23 '09 at 11:51
  • 2
    I know that the ClassCastException guard code appears in the Google sample, but I think it's probably unnecessary. It's not likely that the MenuInfo is only sometimes an AdapterContextMenuInfo - it will probably always or never be. The guard clause stops the app from crashing, but you have a logic bug anyway. I'd personally rather see the whole stack trace, but that's just my preference. – Daniel Yankowsky Jul 20 '09 at 06:42
  • 1
    @Daniel Yankowsky: If you use `registerForContextMenu` only only once: yes. But with a custom list activity layout you might have other elements to register as well. But then: Would it be not better to use `instanceof` and check what you got? — Ahh, well, I never seen any good demo code. – Martin Jun 05 '11 at 17:53
14

You should also look at Activity.registerForContextMenu(View).

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
5
listView = (ListView) findViewById(R.id.listpockets);
registerForContextMenu(listView);



public void onCreateContextMenu(android.view.ContextMenu menu, View v, android.view.ContextMenu.ContextMenuInfo menuInfo) {
    //AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
    menu.setHeaderTitle(getString(R.string.titleDelete));   
    menu.add(0, CommonUtil.CONTEXT_MENU__DELETE_ID, 0, getString(R.string.menuDelete));
};
@Override
public boolean onContextItemSelected(MenuItem item) {

    if(item.getItemId() == CommonUtil.CONTEXT_MENU__DELETE_ID)
    {
       AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
       long id = this.listView.getItemIdAtPosition(info.position);
       Log.d(TAG, "Item ID at POSITION:"+id);
    }
    else
    {
        return false;
    }
    return true;
}
Dhiral Pandya
  • 10,311
  • 4
  • 47
  • 47