xamarin Android -正确使用invalidateOptionsMenu()

gkl3eglg  于 2023-02-01  发布在  Android
关注(0)|答案(9)|浏览(161)

我在invalidateOptionsMenu()上搜索了很多,我知道它是做什么的。但是我想不出这个方法在真实的生活中有什么用处。
我的意思是,举个例子,假设我们想向ActionBar添加一个新的MenuItem,我们可以简单地从onCreateOptionsMenu(Menu 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#语法。

sulc1iza

sulc1iza1#

invalidateOptionsMenu()用于表示Android,菜单内容发生了变化,需要重新绘制菜单,例如,您在运行时单击了一个按钮,增加了另一个菜单项,或者隐藏了菜单项组,这种情况下需要调用invalidateOptionsMenu(),以便系统在UI上重新绘制,此方法是OS调用onPrepareOptionsMenu()的信号。此外,OnCreateOptionsMenu()只在Activity(片段)创建期间调用一次,因此此方法无法处理运行时菜单更改。
所有这些都可以在文档中找到:
系统调用onCreateOptionsMenu()后,它会保留您填充的菜单示例,并且不会再次调用onCreateOptionsMenu(),除非菜单因某种原因失效。但是,您应仅将onCreateOptionsMenu()用于创建初始菜单状态,而不应在Activity生命周期中进行更改。
如果要根据Activity生命周期中发生的事件修改选项菜单,可以使用onPrepareOptionsMenu()方法。此方法将Menu对象按当前存在的形式传递给您,以便您可以修改它,如添加、移除或禁用项目。(Fragments还提供onPrepareOptionsMenu()回调。
在Android 2.3.x及更低版本中,系统在用户每次打开选项菜单(按下菜单按钮)时调用onPrepareOptionsMenu()。
在Android 3.0及更高版本中,当菜单项显示在操作栏中时,选项菜单被视为始终打开。当事件发生且您想要执行菜单更新时,您必须调用invalidateOptionsMenu()以请求系统调用onPrepareOptionsMenu()。

kx1ctssn

kx1ctssn2#

在应用程序生命周期中使用此选项重新加载新菜单:
新增:

getActivity().invalidateOptionsMenu();

旧的

ActivityCompat.invalidateOptionsMenu(getActivity());
0s7z1bwu

0s7z1bwu3#

您需要覆盖方法onPrepareOptionsMenu(),在相同的方法中编写操作菜单的更新代码,如果您正在使用片段,则在onCreateView()中添加setHasOptionsMenu(true);
希望对你有帮助

dddzy1tm

dddzy1tm4#

我发现的一个用途是强制onResumeonCreateOptionsMenu/onPrepareOptionsMenu之间的操作顺序,自然顺序(至少在平台22上)似乎会左右摇摆,特别是在重新定位设备时。
onResume()中调用invalidateOptionsMenu(),您将保证onPrepareOptionsMenu将在onResume之后被调用(它也可能在onResume之前被调用),例如,这将允许基于在onResume中检索的数据来启用菜单项。

ryoqjall

ryoqjall5#

/**
 * Set a hint for whether this fragment's menu should be visible.  This
 * is useful if you know that a fragment has been placed in your view
 * hierarchy so that the user can not currently seen it, so any menu items
 * it has should also not be shown.
 *
 * @param menuVisible The default is true, meaning the fragment's menu will
 * be shown as usual.  If false, the user will not see the menu.
 */
public void setMenuVisibility(boolean menuVisible) {
    if (mMenuVisible != menuVisible) {
        mMenuVisible = menuVisible;
        if (mHasMenu && isAdded() && !isHidden()) {
            mHost.onSupportInvalidateOptionsMenu();
        }
    }
}

XML菜单示例:

<?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>

示例片段中的代码:

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);
}
bgibtngc

bgibtngc6#

1.将菜单的初始状态设置为onCreateOptionsMenu(...)
1.使用invalidateOptionsMenu()强制onCreateOptionsMenu(...)onPrepareOptionsMenu(...)
1.在onPrepareOptionsMenu(...)中,调用menu.clear()从菜单中删除所有项。
1.仍然在onPrepareOptionsMenu(...)的地方你的动态菜单的变化后清除。

pb3skfrl

pb3skfrl7#

编辑:这里有一个更好的答案的问题。
invalidateOptionsMenu()的一个很好的用途是当我们有一个ListView和删除所有MenuItem时,所以当ListView为空时,我们应该使用invalidateOptionsMenu()来删除删除所有MenuItem
下面是一个与此答案相关的问题:Question .

dzhpxtsq

dzhpxtsq8#

它很旧了,但希望这能在未来帮助到一些人。
我在真实的生活场景中发现了一个用途:
假设您有一个存储到数据库中的项目列表,并且您有2个活动:
1.显示活动:从数据库中获取这些对象后显示出来。
1.编辑活动:用于编辑现有项目并将其保存到数据库中。
您决定使用几个选项从DisplayActivity转到EditActivity:

*第一个:将一个全新的项目添加到数据库中。
*第二个:编辑现有项目。

为了避免重复代码,您决定将EditActivity用于这两个目的。
因此,你想根据不同的用途定制选项菜单,在这种情况下,你可以使用onCreateOptionsMenu()构建一个默认的选项菜单,当需要编辑一个现有的项目时,让它保持原样;当需要创建新项目时invalidateOptionsMenu()它;并且在这种情况下,onPrepareOptionsMenu()被自动触发以定制菜单。
例如,“选项”菜单可以有一个用于编辑现有项目的删除选项,并且在添加新项目时应该隐藏该选项。

mefy6pfw

mefy6pfw9#

从片段调用getActivity().invalidateOptionsMenu();

相关问题