Как я могу обновить ActionBar, когда onPrepareOptionsMenu переключил записи меню?

в моих приложениях я часто включаю / отключаю записи меню и делаю их видимыми из onPrepareOptionsMenu.

сегодня я начал добавлять атрибут меню android: showAsAction в некоторые из моих Android 2.x приложения для отображения записей меню, используемых чаще всего на панели действий.

панель действий не отражает включение/выключение и видимость сразу. Мне нужно нажать на выпадающее меню справа, чтобы увидеть это изменение произошло.

Ок, я понимаю, что меню пожары onPrepareOptionsMenu. Но что мне нужно сделать, чтобы обновить 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);
}

EDIT: если я добавлю invalidateOptionsMenu это работает на Android 3.x приложений, но падает на Android 2.X устройств из-за недостающего метода. Каков рекомендуемый способ сделать это правильно?

10 ответов


мой метод выбора-создать вспомогательный класс. Например:

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

Теперь в вашем коде выше, замените invalidateOptionsMenu(); С:

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

кредит на этот метод идет в CommonsWare (поиск HoneycombHelper, и проверить его книги - настоятельно рекомендуется)


благодаря принятому ответу. Я использую ActionBarActivity. в этом классе вы можете использовать

supportInvalidateOptionsMenu();

использовать

ActivityCompat.invalidateOptionsMenu(Activity activity)

С библиотека совместимости.

см.:https://stackoverflow.com/a/14748687/435855


сохраните ссылку в меню и вызовите:

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

теперь вы можете использовать метод supportInvalidateOptionsMenu () из ActionbarActivity с библиотекой поддержки. Таким образом, вам не нужно проверять версию sdk. Идет до API 7 и выше.

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

сделайте так, вы должны импортировать v7 библиотеки поддержки, используя это

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


на основе ответа" Klaasvaak " выше. Я использую его подменю. Это работает для меня :

// 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);

Я не уверен, что вы уже видели это, но если вы широко используете actionbar и планируете поддерживать более низкие API (>8), взгляните на библиотеку actionBarSherlock. Это сделает так, что вам не придется разделять код actionBar для более низких и более высоких API, а затем вы можете просто запустить:

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

getActivity().invalidateOptionsMenu();

получает работу.


Слава @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
}

также убедитесь, что вы не называя

myAppCompatActivity.setToolbarTitle("some dynamic title");

вскоре после того, как вы обновили свое меню.

у меня была проблема, что чертежи не будут отображаться, даже если есть место для их отображения. Как только я изменил ориентацию, появились чертежи.. ?

В Итоге:

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

}