在有多个Fragment的Activity中使用上下文菜单时会出现上下文菜单所执行的命令与被执行的对象不一致的问题。比如:在Fragment(或ListFragment)中含有ListView,你給ListView对象注册了上下文菜单。样例代码:
在上下文菜单的点击实现方法(onContextItemSelected)中执行菜单操作时你会发现被操作的对象似乎总是第一个Fragment中的那个ListView。或者来回切换Fragment时是上一个Fragment里的ListView。这让人有些沮丧。
上面的menu.add的第一个参数指定组ID,你可以給一个固定值。我的代码中用了已有的this.getDataType(),这是一个抽象方法,子类实现中提供这个ID,此处使用正合适。
2)自定义实现ListView的setOnItemLongClickListener处理:
- ListView mListView = (ListView) mRoot.findViewById(R.id.my_listview);
- mListView.setOnCreateContextMenuListener(this);
在上下文菜单的点击实现方法(onContextItemSelected)中执行菜单操作时你会发现被操作的对象似乎总是第一个Fragment中的那个ListView。或者来回切换Fragment时是上一个Fragment里的ListView。这让人有些沮丧。
解决办法:1)在创建上下文菜单时设定不同的组ID(GroupID)。比如:
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- menu.add(this.getDataType(), MENU_EDIT, Menu.NONE, R.string.edit).setIcon(android.R.drawable.ic_menu_edit);
- menu.add(this.getDataType(), MENU_DELETE, Menu.NONE, R.string.delete).setIcon(android.R.drawable.ic_menu_delete);
- super.onCreateContextMenu(menu, v, menuInfo);
- }
上面的menu.add的第一个参数指定组ID,你可以給一个固定值。我的代码中用了已有的this.getDataType(),这是一个抽象方法,子类实现中提供这个ID,此处使用正合适。
然后在上下文命令处理方法中对这个组ID进行判断,仅当属于这个组的命令才执行:
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- if (item.getGroupId() == this.getDataType()) {
- final AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
- if (item.getItemId() == MENU_EDIT) {
- editItem(menuInfo.position); return true;
- }
- else if (item.getItemId() == MENU_DELETE) {
- // ... return true;
- }
- }
- return super.onContextItemSelected(item);
- }
2)自定义实现ListView的setOnItemLongClickListener处理:
- mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
- @Override
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- final int pos = position;
- List<String> list = Lists.newArrayList(getResources().getString(R.string.edit), getResources().getString(R.string.delete));
- Util.newSimpleSelectionDialog(getActivity(), list,
- new DialogClickListener<String>() {
- @Override
- public void onClick(int index, String element) {
- if (index == 0) // edit
- editItem(pos);
- else if (index == 1) { // delete
- }
- }
- }).show();
- return true;
- }
- });
以上两种方法都可很好解决这个问题。至于倾向于哪个解决方法,我觉得自定义方式也不错,尽管需要自定实现菜单显示。