15

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

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

Теперь, на мой вопрос, следует только 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); 
} 

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

P.S. Извините за синтаксис C#.

+0

Какой у вас minSdkVersion? – Xcihnegn

+0

Работает на 11+. Mine is 15. –

+0

Поэтому он должен вызывать OnCreateOptionsMenu(), вы можете попробовать запустить отладку, чтобы пройти через коды – Xcihnegn

ответ

2

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

Надеется, что это поможет вам

+0

в порядке, но onPrepareOptionsMenu() - это только фиксированный метод. По фиксированному я имею в виду, что это не тот случай, когда один раз наPrepareOptionsMenu() что-то делает и в другое время делает что-то еще. –

+0

Почему бы и нет? Знаете, есть такая вещь, как условия (если-еще).Вы можете сделать так, как хотите, в любой ситуации, о которой вы думаете, –

+0

, что и есть мой вопрос. Это единственный подход к использованию этого метода ??? –

44

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

Все можно найти в documentation:

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

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

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

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

+0

, но мне не нужно вызывать invalidateOptionsMenu(). Я просто делаю menu.add(), и это показано –

+0

Это необходимо для динамических меню. Как вы могли бы вызвать 'menu.add () 'извне' onCreateOptionsMenu() '? Как вы могли бы сделать, например, пункты меню меняться, когда пользователь прокручивает список вниз? Недействительным меню на прокрутке, принуждением к его воссозданию и проверкой определенного условия в' onCreateOptionsMenu() '.Это не сработает, если вы проверите условие внутри' onCreateOptionsMenu() 'без аннулирования, потому что активность будет думать, что меню все еще в порядке. – natario

+0

Я не знаю, как писать код здесь, но позволяет: OnCreateOptionsMenu (меню IMenu) { _Menu = menu; } И у вас есть ссылка на Меню. Теперь сделайте все, что вы хотите сделать –

0

Редактировать: Вот лучший ответ на вопрос.

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

Вопрос о данном ответе: Question.

+0

Если у вас есть новый вопрос, пожалуйста, спросите его, нажав кнопку [Ask Question] (http://stackoverflow.com/questions/ask) , Включите ссылку на этот вопрос, если это поможет обеспечить контекст. - [Из обзора] (/ review/low-quality-posts/14147349) – sushildlh

+0

На самом деле эта ссылка предоставляет контекст для ответа @sushildlh –

0
/** 
* 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); 
} 
12

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

ActivityCompat.invalidateOptionsMenu(getActivity()); 
+0

, в котором жизненный цикл фрагмента мы должны назвать этим? –

+2

любой момент жизни. Цикл, щелчок и т. Д. – itzhar

0

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

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

  2. Используйте invalidateOptionsMenu(), чтобы заставить onCreateOptionsMenu (.. .) и onPrepareOptionsMenu (...)

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

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

Надеется, что это помогает ...

0

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^