如何在多片段活动中处理onContextItemSelected?

Lar*_* K. 68 android contextmenu android-fragments android-support-library

我目前正在尝试调整我的应用程序以使用"适用于Android v4的兼容性库",以便为Android 1.6用户提供使用片段的好处.

上下文菜单的实现似乎很棘手:

  • 该应用程序的主要活动是扩展FragmentActivity 类.
  • 这些片段都基于一个扩展Fragment类的类.
  • fragment类在其onCreateView()方法中调用 registerForContextMenu()并覆盖 onCreateContextMenu()onContextItemSelected()方法.

对于onCreateContextMenu(),这非常有效.上下文菜单从资源文件中膨胀,并根据所选项目进行略微修改(基于listView ...即使片段不是ListFragment).

选择上下文菜单项时会发生此问题. 从第一个添加的片段开始,为所有当前存在的片段调用onContextItemSelected().

在我的例子中,片段用于显示文件夹结构的内容.当打开子文件夹片段的上下文菜单并选择菜单项时,首先在上层调用onContextItemSelected()(取决于此时允许/可见的片段数).

现在,我使用活动级别上的字段的变通方法,该字段包含调用其onCreateContextMenu()的最后一个片段的标记.这样,当存储的标记与getTag()不同时,我可以在onContextItemSelected()的开头调用"return super.onContextItemSelected(item)" .但这种方法对我来说有点脏.

为什么在所有片段上调用onContextItemSelected()?而不只是一个调用onCreateContextMenu()的人

处理这个问题最优雅的方法是什么?

Ric*_*mer 68

即使您找到了解决方法,我也会发布一个答案,因为我刚刚处理了类似的问题.当您为特定片段的上下文菜单充气时,为每个菜单项分配一个对片段唯一的groupId.然后在'onContextItemSelected'中测试groupId.例如:

public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
    menu.add(UNIQUE_FRAGMENT_GROUP_ID, MENU_OPTION_1, 0, R.string.src1);
    menu.add(UNIQUE_FRAGMENT_GROUP_ID, MENU_OPTION_2, 0, R.string.src2);
}
public boolean onContextItemSelected(MenuItem item) {
    //only this fragment's context menus have group ID of -1
    if (item.getGroupId() == UNIQUE_FRAGMENT_GROUP_ID) {
        switch(item.getItemId()) {
        case MENU_OPTION_1: doSomething(); break;
        case MENU_OPTION_2: doSomethingElse(); break;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,所有片段仍将接收对'onContextItemSelected'的调用,但只有正确的片段才会响应,因此无需编写活动级代码.我假设即使您没有使用'menu.add(...)',此技术的修改版本也可以工作

  • 你能用return语句更新代码吗?因为它也很重要. (2认同)

Ser*_*tov 55

另一个解决方案:

@Override
public boolean onContextItemSelected(MenuItem item) {
    if (getUserVisibleHint()) {
        // context menu logic
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

基于杰克沃顿的补丁.

  • 我使用了倒置解决方案,它在程序中更容易阅读,并添加到许多片段: (3认同)
  • 不要忘记在if语句中**返回true **,否则可能会遇到麻烦... (2认同)
  • 这是imho的最佳解决方案. (2认同)

aze*_*lez 8

我喜欢Sergei G的简单解决方案(基于Jake Wharton的修复),但因为更容易添加到几个片段中而倒置了:

public boolean onContextItemSelected(android.view.MenuItem item) 
{  
    if( getUserVisibleHint() == false ) 
    {
        return false;
    }

    // The rest of your onConextItemSelect code
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
 }
Run Code Online (Sandbox Code Playgroud)

之后,代码与之前相同.


小智 5

我发现了一个非常简单的解决方案。由于每次创建 ContextMenu 时都会调用 onCreateContextMenu(),因此我将布尔变量设置为 true。

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getActivity().getMenuInflater();
    inflater.inflate(R.menu.film_menu, menu);
    bMenu=true;
}
Run Code Online (Sandbox Code Playgroud)

我唯一要做的另一件事是要求该变量 OnContextItemSelected()

public boolean onContextItemSelected(MenuItem item) {
    if (bMenu) {
        bMenu=false;
        if (item.getItemId() == R.id.filmProperties) {
            ///Your code
            return true;
        } else {
            return super.onContextItemSelected(item);
        }
    } else {
        return super.onContextItemSelected(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

就是这样。

  • 如果在没有选择任何项目的情况下取消上下文菜单怎么办?`bMenu` 将保持为 `true`。 (4认同)

Lar*_* K. 3

我找到了一个替代方案。它不会改变我上面的问题,但它使它变得毫无意义。

我已从我的应用程序中完全删除了上下文菜单。相反,我捕获了对列表项的长按,并此时更改操作栏的可见按钮。从用户的角度来看,这更像是平板电脑的上下文菜单。

在向后兼容的应用程序中,操作栏不存在。因此,我决定为 Honeycomb 之前的设备构建自己的(顶部的工具栏)。

如果您想继续使用上下文菜单,我没有找到更好的解决方案作为我上面提到的解决方法。

  • 对于旧版本的操作栏,请使用 [actionbarsherlock](http://actionbarsherlock.com/) (3认同)