简体   繁体   English

如何使用Fragments在NavigationDrawer上隐藏OptionsMenu?

[英]How to hide OptionsMenu on NavigationDrawer using Fragments?

I am creating android application and I'm trying to respect as much as possible the latest Android usability standards. 我正在创建Android应用程序,我试图尽可能地尊重最新的Android可用性标准。 In particular, I am preparing the user interface using the navigation drawer, and I'm trying to ensure compatibility with 2.1+ Android versions. 特别是,我正在使用导航抽屉准备用户界面,我正在努力确保与2.1+ Android版本的兼容性。 To appreciate the problem, the project consists of: 为了理解这个问题,该项目包括:

  • A main activity; 主要活动;
  • A navigation drawer; 导航抽屉;
  • Four fragments (with their associated layouts). 四个片段(与其相关的布局)。

The problem I'm experiencing occurs when opening the navigation drawer: although each Fragment has its specific menu, when I open the navigation drawer it is added to the nav drawer menu. 打开导航抽屉时遇到的问题是:虽然每个Fragment都有其特定的菜单,但当我打开导航抽屉时,它会被添加到导航抽屉菜单中。 I tried in several ways ( invalidateOptionMenu() , menu.clear() , manipulating functions isDrawerOpen() and isDrawerClose() and more), but I cannot remove the Fragment 's menu when opening the navigationdrawer. 我尝试了几种方法( invalidateOptionMenu()menu.clear() ,操作函数isDrawerOpen()isDrawerClose()等),但是在打开导航器时我无法删除Fragment的菜单。

These are some snippets of my code, much of it generated by Android Studio, the IDE I'm using: 这些是我的代码的一些片段,其中大部分是由Android Studio生成的,我正在使用的IDE:

In main activity: 在主要活动中:

@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);
}

where "global" is a simple menu with a classical "ic_action_overflow". 其中“global”是一个带有经典“ic_action_overflow”的简单菜单。

And in my fragments I've: 在我的片段中,我:

@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);
}

(It's the same of the other Fragment s). (它与其他Fragment相同)。

Someone can give me some advice on how to act? 有人可以就如何采取行动给我一些建议吗?

I faced the same problem using the boilerplate code generated by Android Studio and got it working by modifying the menu in NavigationDrawerFragment.onPrepareOptionsMenu() (in my case, I wanted to clear the menu altogether): 我使用Android Studio生成的样板代码遇到了同样的问题,并通过修改NavigationDrawerFragment.onPrepareOptionsMenu()的菜单来实现它(在我的情况下,我想完全清除菜单):

@Override
public void onPrepareOptionsMenu(Menu menu) {
    if (mDrawerLayout != null && isDrawerOpen()) {
        menu.clear();
    }
}

This is roughly how the options menu is recreated: 这大致是重新创建选项菜单的方式:

  1. NavigationDrawerFragment , which is generated by the IDE, calls supportInvalidateOptionsMenu() when the drawer is opened or closed. NavigationDrawerFragment由IDE生成,在打开或关闭抽屉时调用supportInvalidateOptionsMenu()
  2. onCreateOptionsMenu gets called : The hosting activity and each of the added fragments gets a chance to contribute menu items. 调用onCreateOptionsMenu :托管活动和每个添加的片段都有机会提供菜单项。
  3. onPrepareOptionsMenu gets called : Again, the hosting activity and each of the added fragments get a chance to modify the menu. onPrepareOptionsMenu :再次,托管活动和每个添加的片段都有机会修改菜单。

The fragments are iterated in the order they were added . 片段按添加顺序迭代 There is no way to stop the chain of calls midway in steps 2. and 3. 在步骤2和3中途无法阻止呼叫链。

So the idea is to let NavigationDrawerFragment do last-minute changes to the menu in its onPrepareOptionsMenu and no other fragments. 因此,我们的想法是让NavigationDrawerFragment对其onPrepareOptionsMenu的菜单进行最后一刻的更改,而不是其他片段。

If you need to let other fragments do something in onPrepareOptionsMenu , then you may have to setup those other fragments so they can determine if the drawer is open or not and change their behavior accordingly. 如果您需要让其他片段在onPrepareOptionsMenu执行某些onPrepareOptionsMenu ,那么您可能必须设置其他片段,以便他们可以确定抽屉是否打开并相应地更改其行为。 This may mean perhaps adding a isDrawerOpen method to the hosting activity or passing in the drawer identifiers to the fragment like it's done in NavigationDrawerFragment.setup() . 这可能意味着可能会向托管活动添加isDrawerOpen方法,或者将抽屉标识符传递给片段,就像在NavigationDrawerFragment.setup()完成一样。

In your fragment onCreate, add this : 在你的片段onCreate中,添加:

setHasOptionsMenu (true);

And then hide through onPrepareOptionsMenu. 然后通过onPrepareOptionsMenu隐藏。 eg 例如

@Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        menu.findItem(R.id.action_settings).setVisible(false);
    }

Check out this answer here: https://stackoverflow.com/a/18135409/2558344 . 在这里查看这个答案: https//stackoverflow.com/a/18135409/2558344 Its basically using a boolean to clear items in the navigation drawer and vice versa. 它基本上使用布尔值来清除导航抽屉中的项目,反之亦然。 But alternatively, you could declare Menu menu as a private variable in your class and use it as: onCreateOptionsMenu(menu, MenuInflater inflater) . 但另外,您可以将Menu menu声明为类中的私有变量,并将其用作: onCreateOptionsMenu(menu, MenuInflater inflater)

Then check in your fragments onStop() , onPause() if it's displaying items or not, if yes then clear them, like: 然后检查片段onStop()onPause()是否显示项目,如果是,则清除它们,如:

if (menu != null)
    menu.clear();

If you've implemented the navigation drawer the way Android Studio sets it up for you in its example code with a NavigationDrawerFragment , you should have two xml to start with main.xml (activity wide actionbar menu items) and global.xml (global items). 如果您已经使用NavigationDrawerFragment在其示例代码中为Android Studio设置了导航抽屉,您应该有两个xml以main.xml (活动范围操作栏菜单项)和global.xml (全局项目) global.xml )。 I then added a fragment specific menu which adds items to the "activity menu items" as long as the drawer is closed... 然后,我添加了一个特定于片段的菜单,只要抽屉关闭,它就会将项目添加到“活动菜单项”中...

Activity: 活动:

@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 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);
}

and in your fragments add as you've described above 并在您的片段中添加,如上所述

@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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM