Как скрыть OptionsMenu на NavigationDrawer с помощью фрагментов?
Я создаю приложение для Android, и я стараюсь как можно больше уважать последние стандарты юзабилити Android. В частности, я готовлю пользовательский интерфейс с помощью навигационного ящика, и я пытаюсь обеспечить совместимость с версиями Android версии 2.1+. Чтобы оценить проблему, проект состоит из:
- Основной вид деятельности;
- Ящик для навигации;
- Четыре фрагмента (с соответствующими макетами).
Проблема, с которой я столкнулся, возникает при открытии ящика навигации: хотя каждое Fragment
имеет свое конкретное меню, когда я открываю навигационный ящик, он добавляется в меню навигационного ящика. Я попытался несколькими способами (invalidateOptionMenu()
, menu.clear()
, манипулируя функциями isDrawerOpen()
и isDrawerClose()
и т.д.), Но я не могу удалить меню Fragment
при открытии навигатора.
Вот некоторые фрагменты моего кода, большая часть которых была создана Android Studio, используемой мной IDE:
В основном действии:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.global, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
где "global" - это простое меню с классическим "ic_action_overflow".
И в моих фрагментах я:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment1, menu);
}
(То же самое относится к другим Fragment
s).
Кто-нибудь может дать мне несколько советов о том, как действовать?
Ответы
Ответ 1
Я столкнулся с той же проблемой, используя код шаблона, созданный Android Studio, и заставил его работать, изменив меню в NavigationDrawerFragment.onPrepareOptionsMenu()
(в моем случае я хотел полностью очистить меню):
@Override
public void onPrepareOptionsMenu(Menu menu) {
if (mDrawerLayout != null && isDrawerOpen()) {
menu.clear();
}
}
Это примерно то, как воссоздано меню опций:
-
NavigationDrawerFragment
, который генерируется IDE, вызывает supportInvalidateOptionsMenu()
, когда ящик открыт или закрыт.
-
onCreateOptionsMenu
получает вызов: активность хостинга и каждый добавленный фрагмент получает возможность вносить элементы меню.
-
onPrepareOptionsMenu
получает вызов: снова активность хостинга и каждый из добавленных фрагментов получают возможность изменить меню.
Фрагменты повторяются в том порядке, в котором они были добавлены. Невозможно остановить цепочку вызовов на полпути в шагах 2 и 3.
Итак, идея состоит в том, чтобы позволить NavigationDrawerFragment
вносить в последнюю минуту изменения в меню в onPrepareOptionsMenu
и других фрагментах.
Если вам нужно позволить другим фрагментам что-то сделать в onPrepareOptionsMenu
, вам, возможно, придется настроить эти другие фрагменты, чтобы они могли определить, открыт ли ящик или нет, и соответственно изменить их поведение. Это может означать, что возможно добавить метод isDrawerOpen
к хостинговой деятельности или передать идентификаторы ящика фрагменту, как это сделано в NavigationDrawerFragment.setup()
.
Ответ 2
В вашем фрагменте onCreate добавьте следующее:
setHasOptionsMenu (true);
И затем спрячьтесь в onPrepareOptionsMenu. например
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.action_settings).setVisible(false);
}
Ответ 3
Посмотрите здесь этот ответ: fooobar.com/questions/187809/.... В основном он использует логические для очистки элементов в навигационном ящике и наоборот. Но в качестве альтернативы вы можете объявить Menu menu
как приватную переменную в своем классе и использовать ее как: onCreateOptionsMenu(menu, MenuInflater inflater)
.
Затем проверьте свои фрагменты onStop()
, onPause()
, если он отображает элементы или нет, если да, то очистите их, например:
if (menu != null)
menu.clear();
Ответ 4
Если вы внедрили навигационный ящик так, как Android Studio настроит его в своем примере кода с помощью NavigationDrawerFragment
, вы должны иметь два xml для начала с main.xml
(элементы меню действий в области действия) и global.xml
(глобальные элементы). Затем я добавил меню, специфичное для фрагментов, которое добавляет элементы в "пункты меню действий", пока ящик закрыт...
Активность:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this activity
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
this.menu = menu;
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
NavigationDrawerFragment
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// If the drawer is open, show the global app actions in the action bar.
// See also showGlobalContextActionBar, which controls the top-left area
// of the action bar.
if (mDrawerLayout != null && isDrawerOpen()) {
inflater.inflate(R.menu.global, menu);
showGlobalContextActionBar();
}
super.onCreateOptionsMenu(menu, inflater);
}
и в ваших фрагментах добавьте, как описано выше
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Add fragment specific action bar items to activity action bar items.
// Activity wide items are in main.xml
// Visible action bar items if navigation drawer is visible/open
// are in global.xml
super.onCreateOptionsMenu(menu, inflater);
if (!mNavigationDrawerFragment.isDrawerOpen()) {
inflater.inflate(R.menu.fragment_menu, menu);
}
}