Android - Правильное использование invalidateOptionsMenu()
Я много искал 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. Извините за синтаксис С#.
Ответы
Ответ 1
invalidateOptionsMenu()
используется, чтобы сказать Android, что содержимое меню изменилось, и меню нужно перерисовать. Например, вы нажимаете кнопку, которая добавляет другой элемент меню во время выполнения или скрывает группу элементов. В этом случае вы должны позвонить invalidateOptionsMenu()
, чтобы система могла перерисовать его в пользовательском интерфейсе. Этот метод является сигналом для вызова ОС onPrepareOptionsMenu()
, где вы выполняете необходимые манипуляции с меню.
Кроме того, OnCreateOptionsMenu()
вызывается только один раз во время создания активности (фрагмента), поэтому изменения меню времени выполнения не могут быть обработаны с помощью этого метода.
Все можно найти в документации:
После того, как система вызывает onCreateOptionsMenu(), она сохраняет экземпляр из меню, которое вы заполняете, и не будет вызывать onCreateOptionsMenu() снова если по какой-либо причине меню недействительно. Однако вы должны используйте onCreateOptionsMenu() только для создания начального состояния меню и не вносить изменения во время жизненного цикла деятельности.
Если вы хотите изменить меню опций на основе событий, которые происходят во время жизненного цикла деятельности вы можете сделать это в onPrepareOptionsMenu(). Этот метод передает вам объект Menu поскольку он в настоящее время существует, поэтому вы можете его изменить, например, добавить, удалить или отключить элементы. (Фрагменты также предоставляют onPrepareOptionsMenu() Обратный вызов.)
В Android 2.3.x и ниже система вызывает onPrepareOptionsMenu() каждый раз, когда пользователь открывает меню опций (нажимает кнопку "Меню" ).
В Android 3.0 и выше меню опций считается всегда открывается, когда пункты меню представлены в панели действий. Когда событие происходит, и вы хотите выполнить обновление меню, вы должны позвонить invalidateOptionsMenu(), чтобы запросить вызов системы onPrepareOptionsMenu().
Ответ 2
используйте это для перезагрузки нового меню в течение жизненного цикла приложения:
новые:
getActivity().invalidateOptionsMenu();
старый
ActivityCompat.invalidateOptionsMenu(getActivity());
Ответ 3
Вам нужно переопределить метод onPrepareOptionsMenu()
, записать код действия для обновления в том же методе, а если вы используете фрагмент, то добавьте setHasOptionsMenu(true);
в onCreateView()
.
Надеюсь, это поможет вам
Ответ 4
Одно из применений, которое я нашел, вызывает порядок операций между onResume
и onCreateOptionsMenu/onPrepareOptionsMenu
. Естественный порядок (по крайней мере, на платформе 22), кажется, переворачивается, особенно при переориентации вашего устройства.
Вызовите invalidateOptionsMenu
() в onResume
(), и вы гарантируете, что onPrepareOptionsMenu
будет вызываться после onResume (его можно дополнительно вызвать до). Например, это позволит включить элемент меню на основе данных, полученных в onResume
.
Ответ 5
Лучший способ, который работал у меня, показан ниже
-
Поместите начальное состояние меню в onCreateOptionsMenu (...)
-
Используйте invalidateOptionsMenu(), чтобы принудительно использовать onCreateOptionsMenu (...) и onPrepareOptionsMenu (...)
-
В onPrepareOptionsMenu (...) вызовите menu.clear(), чтобы удалить все элементы из меню.
-
В режиме onPrepareOptionsMenu (...) поместите ваши динамические изменения меню после очистки
Надеюсь, что это поможет...
Ответ 6
Изменить: Вот лучший ответ на вопрос.
Хорошее использование для invalidateOptionsMenu()
- это когда мы имеем ListView
и Delete All MenuItem
, поэтому, когда ListView
пуст, мы должны использовать invalidateOptionsMenu()
для удаления Delete All MenuItem
.
Вот вопрос, связанный с этим ответом: Question.
Ответ 7
/**
* Set a hint for whether this fragment 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 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);
}
Ответ 8
Это старое, но надеюсь, что это поможет кому-то в будущем.
Одно использование, которое я нашел в сценарии из реальной жизни:
Предположим, у вас есть список элементов, которые хранятся в базе данных, и у вас есть 2 действия:
- DisplayActivity: который отображал эти объекты после их получения
из базы данных.
- EditActivity: используется для редактирования существующего элемента & сохранить это в базу данных.
Вы решили использовать несколько вариантов перехода от DisplayActivity к EditActivity:
- Сначала: добавить новый элемент в базу данных.
- Второй: для редактирования существующего элемента.
Чтобы не повторяться, дублируя код, вы решили использовать EditActivity для обеих целей.
И так, вы хотите настроить меню параметров в соответствии с каждой целью. В этом случае вы должны создать меню параметров по умолчанию, используя onCreateOptionsMenu()
, и оставить его как есть, когда придет время редактировать существующий элемент; и invalidateOptionsMenu()
это когда пришло время создавать новые предметы; и в этом случае onPrepareOptionsMenu()
автоматически запускается для настройки вашего меню.
Например, в меню "Параметры" может быть опция удаления для редактирования существующего элемента, и она должна быть скрыта при добавлении нового элемента.
Ответ 9
Из фрагмента звоните getActivity().invalidateOptionsMenu();
.