如何更新ActionBar中显示的菜单项?


93

我有一个包含2个片段的活动。两者都是ListFragments,都向菜单贡献MenuItems。我有一个MenuItem,它已将android:showAsAction属性设置为在ActionBar上显示为按钮。哪个工作正常。

现在MenuItem是依赖状态的。这是“暂停/恢复”菜单选项,用于暂停和恢复队列。我的问题是创建片段时我不知道如何设置它的初始雕像。

它的状态取决于队列是否暂停。所以我有一个AsyncTask来获取队列并根据队列的状态设置一个布尔值(已暂停)。我正在调用onPrepareOptionsMenu来基于队列的最后一个已知状态来设置“暂停”菜单项的文本,并且如果我将MenuItem保留在实际菜单中,则该方法非常有用。您单击菜单图标,将触发onPrepareOptionsMenu并在显示菜单之前对其进行更新。

问题是,如果将相同的MenuItem放在ActionBar(showAsAction)上,如何强制其更新而不必调用onPrepareOptionsMenu?我需要能够执行此操作,因为在首次启动该应用程序时,我发送了一个获取队列的请求,但是在设置并显示了ActionBar之后,任务会返回。我在片段中创建了一个处理程序,每次获取队列更新时都会调用该处理程序,但是从那里,如何更新ActionBar上MenuItem的文本?除了onPrepareOptionMenu中的内容外,我似乎找不到其他方法来操纵当前设置的Menu。

罗伯·W

Answers:


174

选项1:尝试invalidateOptionsMenu()。我不知道这是否会强制立即重绘操作栏。

选项#2:查看是否getActionView()为受影响的返回任何内容MenuItem。可能showAsAction只是为您自动创建操作视图。如果是这样,您大概可以启用/禁用该功能View

除了onPrepareOptionMenu中的内容外,我似乎找不到其他方法来获取当前设置的Menu来进行操作。

您可以挂在Menu上交的物体上onCreateOptionsMenu()。引用文档

您可以安全地按住菜单(以及从菜单创建的任何项目),并根据需要对其进行修改,直到下次调用onCreateOptionsMenu()为止。


2
尝试了选项#1,并且成功了。由于我试图通过单独线程在回调中更新UI,因此由于我实际上不在UI线程上而引发了异常。为了解决这个问题,我创建了一个处理程序,并在调用回调时向处理程序发送刷新消息。但是最终我使用了getActivity()。invalidateOptionsMenu()刷新菜单。
brockoli 2011年

@brockoli:啊,很好!考虑到该方法的Javadocs措辞,我怀疑它是否具有预期的效果,尽管这似乎是他们最初将其添加到API Level 11的原因。很高兴听到它为您工作!
CommonsWare

我一直把头撞在墙上,试图弄清楚这一点,它就像一种魅力!
MinceMan 2012年

7
如果您使用的是支持库,请supportInvalidateOptionsMenu()改用
Tim Kist,2015年

2
@TimKist,supportInvalidateOptionsMenu()现已弃用;您可以放心使用invalidateOptionsMenu()
普里莫兹Kralj

12

在我的情况下:invalidateOptionsMenu只是将文本重新设置为原始文本,但是直接访问菜单项并重新编写所需的文本就可以正常工作:

if (mnuTopMenuActionBar_ != null) {
    MenuItem mnuPageIndex = mnuTopMenuActionBar_
        .findItem(R.id.menu_magazin_pageOfPage_text);

    if (mnuPageIndex != null) {
        if (getScreenOrientation() == 1) {
            mnuPageIndex.setTitle((i + 1) + " von " + pages);
        }
        else {
            mnuPageIndex.setTitle(
                (i + 1) + " + " + (i + 2) + " " + " von " + pages);
        }
        // invalidateOptionsMenu();
    }
}

由于下面的评论,我可以通过以下代码访问菜单项:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.magazine_swipe_activity, menu);
    mnuTopMenuActionBar_ = menu;
    return true;
}

您是如何获得ActionBar视图的句柄的mnuTopMenuActionBar_
Paul Mennega

1
当操作栏初始化时,我将视图保存到一个成员变量中,如下所示:@Override public boolean onCreateOptionsMenu(Menu menu){MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.magazine_swipe_activity,菜单); mnuTopMenuActionBar_ =菜单;返回true;}
cV2 2012年

这样可以解决同步问题吗?我的意思是。您不知道何时要运行onCreateOptionMenu,因此您可能会使用mnuTopMenuActionBar_未初始化的代码来访问代码,对吧?您将如何解决?
acrespo

嘿,如果动作条使用(是的,这里是)这个方法总是被调用,所以有与没有问题... ...(直接活动开始)stackoverflow.com/questions/7705927/...
CV2

11

要从Fragment刷新菜单,只需调用:

getActivity().invalidateOptionsMenu();

4

我使用了以下代码:

public boolean onPrepareOptionsMenu (Menu menu) {       
    MenuInflater inflater = getMenuInflater();
    TextView title  = (TextView) findViewById(R.id.title);
    menu.getItem(0).setTitle(
        getString(R.string.payFor) + " " + title.getText().toString());
    menu.getItem(1).setTitle(getString(R.string.payFor) + "...");
    return true;        
}

对我来说就像是一种魅力,您可以在这里找到OnPrepareOptionsMenu


4
MenuInflater的目的是什么?
IgorGanapolsky


2

首先,请先按照两行代码更新操作栏项目,然后再在oncreateOptionMenu()中设置条件。例如:

Boolean mISQuizItemSelected = false;

/**
 * Called to inflate the action bar menus
 *
 * @param menu
 *      the menu
 *
 * @return true, if successful
 */

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu items for use in the action bar

    inflater.inflate(R.menu.menu_demo, menu);

    //condition to hide the menus
    if (mISQuizItemSelected) {
        for (int i = 0; i < menu.size(); i++) {
            menu.getItem(i).setVisible(false);
        }
    }

    return super.onCreateOptionsMenu(menu);
}

/**
 * Called when the item on the action bar being selected.
 *
 * @param item
 *      menuitem being selected
 *
 * @return true if the menuitem id being selected is matched
 * false if none of the menuitems id are matched
 */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getId() == R.id.action_quiz) {
        //to navigate based on the usertype either learner or leo
        mISQuizItemSelected = true;

        ActionBar actionBar = getActionBar();
        invalidateOptionMenu();
    }
}

1

为了清楚起见,我认为可以从以下示例中获取资源的直接示例,我认为通过快速直接的示例有助于解决该问题。

private MenuItem menuItem_;

@Override
public boolean onCreateOptionsMenu(Menu menuF) 
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_layout, menuF);
    menuItem_ = menuF.findItem(R.id.menu_item_identifier);
    return true;
}

在这种情况下,您应从头开始保留MenuItem引用,然后在以后的给定时间点更改其状态(例如,更改图标状态)。


-1

Kotlin 1.2中,只需调用:

invalidateOptionsMenu()

然后该onCreateOptionsMenu函数将再次被调用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.