Как скрыть 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);
    }
}