当onPrepareOptionsMenu切换菜单条目时,如何刷新ActionBar?

Har*_*elm 60 android menu android-actionbar

在我的应用程序中,我经常启用/禁用菜单条目,并从onPrepareOptionsMenu中看到它们.

今天我开始将android:showAsAction菜单属性添加到我的一些Android 2.x应用程序中,以显示ActionBar上最常用的菜单条目.

ActionBar不会立即反映启用/禁用和可见性.我需要点击右边的菜单下拉菜单才能看到这种变化.

好的,我知道菜单会在PrepareOptionsMenu上触发.但是我需要做些什么才能刷新ActionBar?我认为这个变化需要从onOptionsItemSelected中应用,但我不知道应该调用什么.

这是菜单:

<item
    android:icon="@drawable/ic_menu_mapmode"
    android:id="@+id/men_mapview"
    android:showAsAction="ifRoom|withText"
    android:title="@string/txt_mapview" />

<item
    android:icon="@drawable/ic_menu_mapmode"
    android:id="@+id/men_satelliteview"
    android:showAsAction="ifRoom|withText"
    android:title="@string/txt_satelliteview" />
Run Code Online (Sandbox Code Playgroud)

这是onPrepareOptionsMenu:

@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
    MenuItem menuItemMapView = menu.findItem(R.id.men_mapview);
    MenuItem menuItemSatelliteView = menu.findItem(R.id.men_satelliteview);

    if (mapView.isSatellite()) {
        menuItemMapView.setEnabled(true).setVisible(true);
        menuItemmenuItemSatelliteView.setEnabled(false).setVisible(false);
    } else {
        menuItemMapView.setEnabled(false).setVisible(false);
        menuItemmenuItemSatelliteView.setEnabled(true).setVisible(true);
    }

    return super.onPrepareOptionsMenu(menu);
}
Run Code Online (Sandbox Code Playgroud)

这是onOptionsItemSelected

@Override
public boolean onOptionsItemSelected(final MenuItem menuItem) {
    switch (menuItem.getItemId()) {
        case R.id.men_mapview:
            mapView.setSatellite(false);
            mapView.setStreetView(true);
            mapView.invalidate();

            invalidateOptionsMenu(); // This works on Android 3.x devices only
            return true;
        case R.id.men_satelliteview:
            mapView.setSatellite(true);
            mapView.setStreetView(false);
            mapView.invalidate();

            invalidateOptionsMenu(); // This works on Android 3.x devices only
            return true;
    }

    return super.onOptionsItemSelected(menuItem);
}
Run Code Online (Sandbox Code Playgroud)

编辑:如果我添加invalidateOptionsMenu这适用于Android 3.x应用程序,但由于缺少方法在Android 2.x设备上崩溃.建议的方法是什么?

wir*_*bly 84

我的选择方法是创建一个帮助器类.例如:

class VersionHelper
{
    static void refreshActionBarMenu(Activity activity)
    {
        activity.invalidateOptionsMenu();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在上面的代码中,替换invalidateOptionsMenu();为:

if (Build.VERSION.SDK_INT >= 11)
{
    VersionHelper.refreshActionBarMenu(this);
}
Run Code Online (Sandbox Code Playgroud)

这种方法的功劳归功于CommonsWare(搜索HoneycombHelper,查看他的书籍 - 强烈推荐)

  • @towpse他将helper类结构化的原因是避免因非向后兼容性而导致崩溃.方法`invalidateOptionsMenu()`仅存在于API 11(蜂窝)及以上版本中.因此,如果您的应用程序要在低于API 11的任何内容上运行,它将崩溃.为了避免这种情况,你将问题中的方法包装在另一个**static**方法中(例如`refreshActionBarMenu()`)和****如果你在API> 11上运行则调用这个静态方法(因此版本检查_before_你调用静态方法).这是因为在您实际使用它之前不会加载`VersionHelper`类. (10认同)
  • 您的答案与简单地将版本检查放在他最初调用if(Build.VERSION.SDK_INT> = 11){invalidateOptionsMenu();之间的区别是什么?}?你可以在versionHelper方法调用中坚持版本检查吗? (5认同)
  • @towpse我现在正在弄清楚这种情况.我相信在这种情况的'else`情况下你应该什么也不做.这是因为执行菜单更新的旧方法(在API11之前)位于方法`onPrepareOptionsMenu`中,每次用户打开菜单时都会自动调用它.因此,为了处理较旧的操作系统和较新的API> 11,您将菜单更改的代码放在`onPrepareOptionsMenu`中(这是为了处理旧操作系统),然后处理更新的操作系统,当事件发生时,您调用`invalidateOptionsMenu`会触发菜单更改. (3认同)

jer*_*bos 67

感谢接受的答案.我正在使用ActionBarActivity.在这个课程中你可以使用

supportInvalidateOptionsMenu();
Run Code Online (Sandbox Code Playgroud)

  • 给这个人一个cookie ....我无法将菜单的可见性设置为false的原因是我只使用了invalidateOptionsMenu(); 直到我找到你的答案.多谢,伙计. (4认同)
  • 这应该是选定的答案. (4认同)

Uri*_*zev 14

使用

ActivityCompat.invalidateOptionsMenu(Activity activity)
Run Code Online (Sandbox Code Playgroud)

来自兼容性库.

请参阅:https://stackoverflow.com/a/14748687/435855


Kla*_*aak 11

保存对菜单的引用并调用:

this.menu.clear();
this.onCreateOptionsMenu(this.menu);
Run Code Online (Sandbox Code Playgroud)

  • 这是如何在API 11之前的设备上以编程方式切换操作栏中选项菜单项的可见性的正确答案. (3认同)