it-swarm.com.ru

Android - правильное использование invalidateOptionsMenu ()

Я много искал на invalidateOptionsMenu(), и я знаю, что он делает. Но я не могу вспомнить ни одного реального примера, где этот метод мог бы быть полезным.

Я имею в виду, например, что мы хотим добавить новый MenuItem к нашему ActionBar, мы можем просто получить Меню из onCreateOptionsMenu(Menu menu) и использовать его в любом действии кнопки.

Теперь на мой реальный вопрос, следует ли использовать only способ использования invalidateOptionsMenu()?

bool _OtherMenu;
protected override void OnCreate (Bundle bundle)
{
    _OtherMenu = false;
    base.OnCreate (bundle);
    SetContentView (Resource.Layout.Main);
    Button button = FindViewById<Button> (Resource.Id.myButton);
    button.Click += delegate
    {
        if(_OtherMenu)
            _OtherMenu = false;
        else
            _OtherMenu = true;

        InvalidateOptionsMenu ();
    };
}

public override bool OnCreateOptionsMenu (IMenu menu)
{
    var inflater = this.SupportMenuInflater;
    if(_OtherMenu)
        inflater.Inflate (Resource.Menu.another_menu, menu);
    else
        inflater.Inflate (Resource.Menu.main_activity_menu, menu);

    return base.OnCreateOptionsMenu (menu);
}

Нажмите кнопку, и появится другое меню. Нажмите кнопку еще раз, и появится предыдущее меню.

Постскриптум Извините за синтаксис C #.

25
Bugs Happen

invalidateOptionsMenu() используется, чтобы сказать Android, что содержимое меню изменилось, и меню должно быть перерисовано. Например, вы нажимаете кнопку, которая добавляет другой элемент меню во время выполнения, или скрывает группу элементов меню. В этом случае вы должны вызвать invalidateOptionsMenu(), чтобы система могла перерисовать его в пользовательском интерфейсе. Этот метод является сигналом для ОС для вызова onPrepareOptionsMenu(), где вы реализуете необходимые манипуляции с меню . Кроме того, OnCreateOptionsMenu() вызывается только один раз во время создания действия (фрагмента), поэтому изменения во время выполнения меню не могут быть обработаны этим методом.

Все можно найти в документации :

После того, как система вызывает onCreateOptionsMenu (), она сохраняет экземпляр меню, которое вы заполняете и больше не будете вызывать onCreateOptionsMenu () если меню по какой-то причине не будет отменено. Тем не менее, вы должны используйте onCreateOptionsMenu () только для создания начального состояния меню и не вносить изменения в течение жизненного цикла деятельности.

Если вы хотите изменить меню параметров на основе событий, которые происходят во время жизненного цикла действия вы можете сделать это в Метод onPrepareOptionsMenu (). Этот метод передает вам объект Menu как он существует в настоящее время, так что вы можете изменить его, например, добавить, удалить или отключить предметы. (Фрагменты также предоставляют обратный вызов onPrepareOptionsMenu () )

На Android 2.3.x и ниже система вызывает функцию PrepreOOptionsMenu () каждый раз, когда пользователь открывает меню опций (нажимает кнопку меню).

На Android 3.0 и выше меню опций всегда считается открыть, когда пункты меню представлены в панели действий. Когда событие происходит, и вы хотите выполнить обновление меню, вы должны позвонить invalidateOptionsMenu () для запроса системного вызова onPrepareOptionsMenu ().

55
Alexander Zhak

используйте это, чтобы перезагрузить новое меню в течение жизненного цикла приложения:

ActivityCompat.invalidateOptionsMenu(getActivity());
17
itzhar

Вам нужно переопределить метод onPrepareOptionsMenu(), написать свой код обновления меню действий в том же методе и, если вы используете фрагмент, добавить setHasOptionsMenu(true); в onCreateView().

Надеюсь, это поможет вам

2
Richa

Одно из применений, которое я нашел, - форсирование порядка операций между onResume и onCreateOptionsMenu/onPrepareOptionsMenu. Кажется, что естественный порядок (по крайней мере, для платформы 22) меняется, особенно при переориентации вашего устройства.

Вызовите invalidateOptionsMenu () в onResume (), и вы гарантируете, что onPrepareOptionsMenu будет вызываться после onResume (он может дополнительно вызываться раньше). Например, это позволит включить пункт меню на основе данных, полученных в onResume.

1
Goose
/**
 * Set a hint for whether this fragment's menu should be visible.  This
 * is useful if you know that a fragment has been placed in your view
 * hierarchy so that the user can not currently seen it, so any menu items
 * it has should also not be shown.
 *
 * @param menuVisible The default is true, meaning the fragment's menu will
 * be shown as usual.  If false, the user will not see the menu.
 */
public void setMenuVisibility(boolean menuVisible) {
    if (mMenuVisible != menuVisible) {
        mMenuVisible = menuVisible;
        if (mHasMenu && isAdded() && !isHidden()) {
            mHost.onSupportInvalidateOptionsMenu();
        }
    }
}

Пример меню XML:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<item
    Android:id="@+id/action_edit"
    Android:icon="@drawable/ic_edit"
    Android:title="Edit Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_delete"
    Android:icon="@drawable/ic_delete"
    Android:title="Delete Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_check"
    Android:icon="@drawable/ic_check"
    Android:title="Check Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_uncheck"
    Android:icon="@drawable/ic_undo"
    Android:title="Uncheck Task"
    app:showAsAction="always" />
</menu>

Код внутри фрагмента образца:

private boolean isMenuItemChecked;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setMenuVisibility(false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.my_menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    try {
        menu.findItem(R.id.action_check).setVisible(!isMenuItemChecked);
        menu.findItem(R.id.action_uncheck).setVisible(isMenuItemChecked);
    }
    catch(Exception e) {
        Log.e(TAG, "onPrepareOptionsMenu error");
    }
}

public void loadUi(boolean isMenuItemChecked) {
    this.isMenuItemChecked = isMenuItemChecked;
    setMenuVisibility(true);
}
0
Francesco Santagati

Лучший способ, который работал для меня, показан ниже

  1. Поместите начальное состояние меню в onCreateOptionsMenu (...)

  2. Используйте invalidateOptionsMenu () для принудительного включения onCreateOptionsMenu (...) и onPrepareOptionsMenu (...)

  3. В onPrepareOptionsMenu (...) вызовите menu.clear (), чтобы удалить все элементы из меню.

  4. Все еще в onPrepareOptionsMenu (...) размещайте динамические изменения меню после очистки

Надеюсь это поможет...

0
Kwame Opare Asiedu

Правка: вот лучший ответ на вопрос.

Хорошее применение для invalidateOptionsMenu() - это когда у нас есть ListView и Delete All MenuItem, поэтому, когда ListView пуст, мы должны использовать invalidateOptionsMenu() для удаления Delete All MenuItem.

Вот вопрос, связанный с этим ответом: Вопрос .

0
user7086724