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

时间:2011-10-14 08:49:46

标签: 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" />

这是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);
}

这是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);
}

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

10 个答案:

答案 0 :(得分:81)

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

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

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

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

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

答案 1 :(得分:66)

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

supportInvalidateOptionsMenu();

答案 2 :(得分:14)

使用

ActivityCompat.invalidateOptionsMenu(Activity activity)

来自compatibility library

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

答案 3 :(得分:10)

保存对菜单的引用并致电:

this.menu.clear();
this.onCreateOptionsMenu(this.menu);

答案 4 :(得分:4)

您现在可以使用ActionbarActivity中的supportInvalidateOptionsMenu()方法和支持库。所以你不必检查sdk的版本。直到API 7及以上版本。

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

这样做,您必须使用此

导入支持库的v7

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

答案 5 :(得分:3)

根据上面的“Klaasvaak”回答。我正在使用它的subMenus。这对我有用:

// Declare and save the menu as global, so it can be called anywhere.
Menu absTopSubMenus;

public boolean onCreateOptionsMenu(Menu menu) {

absTopSubMenus = menu;  // Used for re-drawing this menu anywhere in the codes.

// The remainder of your code below
}

然后,要重新绘制它,只需调用:

// Redraw the top sub-menu
absTopSubMenus.clear();
onCreateOptionsMenu(absTopSubMenus);

答案 6 :(得分:3)

我不确定您是否已经看过它,但如果您广泛使用操作栏,并计划支持较低的API(&gt; 8),请查看actionBarSherlock库。它将使您不必为较低和较高的API分配actionBar代码,然后您可以运行:

runOnUiThread(new Runnable(){
  @Override
  public void run(){
    supportInvalidateOptionsMenu();
  }
});

答案 7 :(得分:2)

  

getActivity()invalidateOptionsMenu();

完成工作。

答案 8 :(得分:1)

感谢@Klaasvaak向我们展示了这里的方式。我使用以下适用于API级别11之前和之后的步骤:

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

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

当然,您必须保存对菜单的引用(在本例中为mOptionsMenu),我通过以下方式完成:

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

    //... create and manage the menu normally
}

答案 9 :(得分:0)

还要确保你没有打电话

myAppCompatActivity.setToolbarTitle("some dynamic title");
在刷新菜单后不久

我遇到的问题是,即使有足够的空间展示,抽奖也不会出现。一旦我进行了方向改变,那么drawables就出现了吗?

摘要:

MainActivity:

public class MainActivity extends AppCompatActivity {

    private boolean showMenu = true;

    public void setShowMenu(boolean show) {
        showMenu = show;
        supportInvalidateOptionsMenu();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.my_menu, menu);
        menu.findItem(R.id.menu_share).setVisible(showMenu);
        // menu.findItem(...
        return true;
    }
}

FragmentNoMenu:

public abstract class FragmentNoMenu extends Fragment {

    protected MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        mainActivity = (MainActivity) getActivity();
        if (mainActivity != null) {
            mainActivity.setShowMenu(false);
        }
    }

}

FragmentWithMenu:

public abstract class FragmentWithMenu extends Fragment {

    protected MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        mainActivity = (MainActivity) getActivity();
        if (mainActivity != null) {
            mainActivity.setShowMenu(true);
        }
    }

}