How can I refresh the ActionBar when onPrepareOpti

2019-01-10 12:02发布

Within my apps I often enable/disable menu entries and do make them visible from onPrepareOptionsMenu.

Today I started to add the android:showAsAction menu attribute to some of my Android 2.x apps to show menu entries used most on the ActionBar.

The ActionBar does not reflect the enable/disable and visibility immediately. I need to click on the menu dropdown on the right to see this change happen.

Ok, I do understand that the menu fires onPrepareOptionsMenu. But what do I need to do to refresh the ActionBar? I think this change needs to be applied from within onOptionsItemSelected but I don't know what I should call.

Here's the menu:

<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" />

Here's the 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);
}

Here's the 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);
}

EDIT: If I add invalidateOptionsMenu this works on Android 3.x apps but crashes on Android 2.x devices because of a missing method. What's the recommended way to do it right?

10条回答
孤傲高冷的网名
2楼-- · 2019-01-10 12:47

Kudos to @Klaasvaak for showing us the way here. I use the following which works on both pre- and post- API Level 11:

private void invalidOptionsMenuHelper() {
    if (Build.VERSION.SDK_INT >= 11) {
        invalidateOptionsMenu();

    } else if (mOptionsMenu != null) {
        mOptionsMenu.clear();
        onCreateOptionsMenu(mOptionsMenu);
    }
}

Of course, you must save a reference to the menu (mOptionsMenu in this case) which I accomplish via:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    mOptionsMenu = menu;

    //... create and manage the menu normally
}
查看更多
老娘就宠你
3楼-- · 2019-01-10 12:50

Use

ActivityCompat.invalidateOptionsMenu(Activity activity)

from the compatibility library.

See: https://stackoverflow.com/a/14748687/435855

查看更多
放我归山
4楼-- · 2019-01-10 12:51

My method of choice is to create a helper class. For example:

class VersionHelper
{
    static void refreshActionBarMenu(Activity activity)
    {
        activity.invalidateOptionsMenu();
    }
}

Now in your code above, replace invalidateOptionsMenu(); with:

if (Build.VERSION.SDK_INT >= 11)
{
    VersionHelper.refreshActionBarMenu(this);
}

Credit for this method goes to CommonsWare (search for HoneycombHelper, and check out his books - highly recommended)

查看更多
狗以群分
5楼-- · 2019-01-10 12:51

I am not sure you have seen it already, but if you use the actionbar extensively, and plan on supporting lower API's (>8), take a look at the actionBarSherlock library. It will make it so you do not have to section your actionBar code for lower and Higher API's, and then you can just run:

runOnUiThread(new Runnable(){
  @Override
  public void run(){
    supportInvalidateOptionsMenu();
  }
});
查看更多
Melony?
6楼-- · 2019-01-10 12:56

You can now use supportInvalidateOptionsMenu() method from the ActionbarActivity with the support library. So you don't have to check for the version of the sdk. Goes until API 7 and above.

http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html

do to so, you have to import the v7 of the support library using this

http://developer.android.com/tools/support-library/setup.html

查看更多
唯我独甜
7楼-- · 2019-01-10 12:56

getActivity().invalidateOptionsMenu();

gets the job done.

查看更多
登录 后发表回答