做了一个小的app,其中用到了tab形式的actionBar和多个fragment,后来因为需求需要在某两个fragment中加入context menu,加入后添加onContextItemSelected事件响应菜单按下的效果,一开始运行正常,在两个fragment中打开context menu正常,两个fragment中的菜单响应事件也正常,后来改动了一些代码后突然发现菜单响应的不正确了,只有一个fragment中的菜单有响应,另外一个没响应。经过一番修改后,发现是onContextItemSelected的返回值影响到了菜单点击事件的执行。
我们先来看一下onContextItemSelected的官方描述:
1 2 3 4 5 6 7 8 9 10 11 |
This hook is called whenever an item in a context menu is selected. The default implementation simply returns false to have the normal processing happen (calling the item's Runnable or sending a message to its Handler as appropriate). You can use this method for any items for which you would like to do processing without those other facilities. Use getMenuInfo() to get extra information set by the View that added this menu item. Derived classes should call through to the base class for it to perform the default menu handling. Parameters item The context menu item that was selected. Returns boolean Return false to allow normal context menu processing to proceed, true to consume it here. |
我们主要看这个返回值部分,返回为了一布尔型变量,当返回false值时由系统去决定此菜单事件的响应流程,返回true则表示菜单响应到此为止,停止后面的流程。
本人没做深入研究,猜想大概流程是这样的,因为在fragment中调用context menu中通过如下方式
1 2 3 4 |
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { getActivity().getMenuInflater().inflate(R.menu.menu_goodlist_item, menu); } |
是通过父activity来填充这个弹出菜单,所以首先是父activity先接收到onContextItemSelected事件,如果父activity中不做处理,则activity会把这个事件分发到各个fragment中去,本人在此次犯的错误就是在子fragment中的onContextItemSelected事件中返回了true值,所以只在一个fragment中响应了事件,另外一个没有响应。
既然在所有的fragment中都会响应onContextItemSelected这个事件,那么我们在每个fragment中处理该事件的时候就需要做一些判断,以避免多个fragment同时执行这个事件,这个是非常重要的,因为不做判断很可能出现一些莫名奇妙的而且不好测试的问题。如下例子:
1 2 3 4 5 6 7 8 9 |
@Override public boolean onContextItemSelected(MenuItem item) { super.onContextItemSelected(item); if(item.getItemId() == R.id.menu_edit_good || item.getItemId() == R.id.menu_delete_good){ ... } return false; } |