Подтвердить что ты не робот

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

В моих приложениях я часто включаю/выключаю записи меню и делаю их видимыми с 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);
}

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

supportInvalidateOptionsMenu();

Ответ 4

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

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

Ответ 5

Теперь вы можете использовать метод 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

Ответ 6

Основываясь на ответе "Клаасваак" выше. Я использую его 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);

Ответ 7

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

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

Ответ 8

getActivity() invalidateOptionsMenu();.

выполняет задание.

Ответ 9

Престижность @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
}

Ответ 10

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

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

}