Android - 正确使用invalidateOptionsMenu()

时间:2015-01-16 12:31:33

标签: android android-actionbar xamarin android-menu android-optionsmenu

我一直在invalidateOptionsMenu()上搜索,我知道它的作用。但是我想不出这个方法可能有用的任何现实生活中的例子。

我的意思是,例如,我们想要向我们的MenuItem添加新的ActionBar,我们只需从onCreateOptionsMenu(Menu menu)获取菜单并将其用于任何按钮的动作。

现在我真正的问题是,遵循方式使用invalidateOptionsMenu()

bool _OtherMenu;
protected override void OnCreate (Bundle bundle)
{
    _OtherMenu = false;
    base.OnCreate (bundle);
    SetContentView (Resource.Layout.Main);
    Button button = FindViewById<Button> (Resource.Id.myButton);
    button.Click += delegate
    {
        if(_OtherMenu)
            _OtherMenu = false;
        else
            _OtherMenu = true;

        InvalidateOptionsMenu ();
    };
}

public override bool OnCreateOptionsMenu (IMenu menu)
{
    var inflater = this.SupportMenuInflater;
    if(_OtherMenu)
        inflater.Inflate (Resource.Menu.another_menu, menu);
    else
        inflater.Inflate (Resource.Menu.main_activity_menu, menu);

    return base.OnCreateOptionsMenu (menu);
}

单击按钮,将出现另一个菜单。再次单击该按钮,将出现上一个菜单。

P.S。对不起C#语法。

9 个答案:

答案 0 :(得分:59)

invalidateOptionsMenu()用于说Android,菜单内容已更改,菜单应重新绘制。例如,单击在运行时添加另一个菜单项的按钮,或隐藏菜单项组。在这种情况下,您应该调用invalidateOptionsMenu(),以便系统可以在UI上重绘它。此方法是OS调用onPrepareOptionsMenu()的信号,您可以在其中实现必要的菜单操作。 此外,OnCreateOptionsMenu()在活动(片段)创建期间仅被调用一次,因此此方法无法处理运行时菜单更改。

所有内容都可以在documentation中找到:

  

系统调用onCreateOptionsMenu()后,它会保留一个实例   您填充的菜单,并且不会再次调用onCreateOptionsMenu()   除非由于某种原因菜单失效。但是,你应该   使用onCreateOptionsMenu()仅创建初始菜单状态和   不要在活动生命周期中进行更改。

     

如果要根据发生的事件修改选项菜单   在活动生命周期中,你可以这样做   onPrepareOptionsMenu()方法。此方法将传递Menu对象   因为它当前存在,所以你可以修改它,如添加,删除或   禁用项目。 (片段还提供onPrepareOptionsMenu()   回调。)

     

在Android 2.3.x及更低版本上,系统调用onPrepareOptionsMenu()   每次用户打开选项菜单(按菜单按钮)。

     

在Android 3.0及更高版本中,选项菜单始终被视为   菜单项在操作栏中显示时打开。当一个事件   发生并且您想要执行菜单更新,您必须调用   invalidateOptionsMenu()请求系统调用   onPrepareOptionsMenu()。

答案 1 :(得分:18)

使用此命令在应用生命周期中重新加载新菜单:

grep

答案 2 :(得分:2)

您需要覆盖方法onPrepareOptionsMenu(),以相同的方法编写操作菜单的更新代码,如果您使用的是片段,请在setHasOptionsMenu(true);中添加onCreateView()

希望它可以帮到你

答案 3 :(得分:1)

我发现的一个用途是强制onResumeonCreateOptionsMenu/onPrepareOptionsMenu之间的操作顺序。自然顺序(至少从平台22开始)似乎会翻转,特别是在重新定位设备时。

invalidateOptionsMenu()中调用onResume(),您将保证在onResume之后调用onPrepareOptionsMenu(之前可能另外调用它)。例如,这将允许根据onResume中检索到的数据启用菜单项。

答案 4 :(得分:0)

编辑:这是一个更好的答案。

invalidateOptionsMenu()的良好用途是我们有ListView和全部删除MenuItem所以当ListView为空时,我们应该使用invalidateOptionsMenu()删除全部删除MenuItem

以下是与此答案相关的问题:Question

答案 5 :(得分:0)

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/action_edit"
    android:icon="@drawable/ic_edit"
    android:title="Edit Task"
    app:showAsAction="always" />

<item
    android:id="@+id/action_delete"
    android:icon="@drawable/ic_delete"
    android:title="Delete Task"
    app:showAsAction="always" />

<item
    android:id="@+id/action_check"
    android:icon="@drawable/ic_check"
    android:title="Check Task"
    app:showAsAction="always" />

<item
    android:id="@+id/action_uncheck"
    android:icon="@drawable/ic_undo"
    android:title="Uncheck Task"
    app:showAsAction="always" />
</menu>

XML菜单示例:

private boolean isMenuItemChecked;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setMenuVisibility(false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.my_menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    try {
        menu.findItem(R.id.action_check).setVisible(!isMenuItemChecked);
        menu.findItem(R.id.action_uncheck).setVisible(isMenuItemChecked);
    }
    catch(Exception e) {
        Log.e(TAG, "onPrepareOptionsMenu error");
    }
}

public void loadUi(boolean isMenuItemChecked) {
    this.isMenuItemChecked = isMenuItemChecked;
    setMenuVisibility(true);
}

示例片段中的代码:

$c = @($a | ? { $b -contains $_ })

答案 6 :(得分:0)

对我有用的最佳方式如下所示

  1. 将菜单的初始状态放在onCreateOptionsMenu(...)

  2. 使用invalidateOptionsMenu()强制onCreateOptionsMenu(...)和onPrepareOptionsMenu(...)

  3. 在onPrepareOptionsMenu(...)中,调用menu.clear()删除菜单中的所有项目。

  4. 仍然在onPrepareOptionsMenu(...)中,您的动态菜单会在清除后发生变化

  5. 希望这会有所帮助......

答案 7 :(得分:0)

它已经很旧了,但希望这对以后的工作有所帮助。

我在现实生活中发现的一种用途:

假设您有一个存储在数据库中的项目列表,并且有2个活动:

  1. DisplayActivity :在获取对象后显示这些对象 从数据库中获取。
  2. EditActivity :用于编辑现有项目并将其保存到数据库中。

您决定从DisplayActivity到EditActivity有两个选择:

  • 第一:要向数据库中添加一个全新的项目。
  • 第二:编辑现有项目。

为了避免重复代码来重复自己,您决定同时使用EditActivity。

因此,您想根据每种目的来自定义“选项菜单”。在这种情况下,您将使用onCreateOptionsMenu()构建默认选项菜单,并在需要编辑现有项目时将其保留为原样。和invalidateOptionsMenu()它是时候创建新项目了;并且在这种情况下,会自动触发onPrepareOptionsMenu()来自定义菜单。

例如,“选项”菜单可以具有用于编辑现有项目的删除选项,并且在添加新项目时应将其隐藏。

答案 8 :(得分:0)

通过片段调用getActivity().invalidateOptionsMenu();