Android 当导航抽屉滑动任意数量时隐藏ActionBar菜单项

Android 当导航抽屉滑动任意数量时隐藏ActionBar菜单项,android,actionbarsherlock,navigation-drawer,Android,Actionbarsherlock,Navigation Drawer,我正在尝试实现一个导航抽屉,每当抽屉打开时,它都会隐藏ActionBar中的菜单项 我正在关注谷歌的文档,但是他们的代码并没有产生预期的行为 使用此代码,当抽屉完全打开时,菜单项隐藏,当抽屉完全关闭时,菜单项显示 然而,Gmail应用程序的表现却不同。只要抽屉打开任意数量,菜单项就会隐藏。这就是我想要的行为。有人知道如何做到这一点吗 谢谢 您是否尝试过以下方法: 通过测量滑动偏移量,在切换导航抽屉时使用invalidateOptions功能表() 在OnPrepareOptions菜单(菜单菜

我正在尝试实现一个导航抽屉,每当抽屉打开时,它都会隐藏ActionBar中的菜单项

我正在关注谷歌的文档,但是他们的代码并没有产生预期的行为

使用此代码,当抽屉完全打开时,菜单项隐藏,当抽屉完全关闭时,菜单项显示

然而,Gmail应用程序的表现却不同。只要抽屉打开任意数量,菜单项就会隐藏。这就是我想要的行为。有人知道如何做到这一点吗

谢谢

您是否尝试过以下方法:

  • 通过测量滑动偏移量,在切换导航抽屉时使用
    invalidateOptions功能表()
  • OnPrepareOptions菜单(菜单菜单)
    中的每个菜单项上迭代并隐藏它

    @Override
    
    public boolean onPrepareOptionsMenu(Menu menu) {
    
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = shouldGoInvisible;
        hideMenuItems(menu, !drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
    
    private void hideMenuItems(Menu menu, boolean visible)
    {
    
        for(int i = 0; i < menu.size(); i++){
    
            menu.getItem(i).setVisible(visible);
    
        }
    }
    
    @覆盖
    公共布尔值OnPrepareOptions菜单(菜单){
    //如果导航抽屉打开,则隐藏与内容视图相关的操作项
    布尔值drawerropen=shouldGoInvisible;
    hideMenuItems(菜单,!抽屉);
    返回super.onPrepareOptions菜单(菜单);
    }
    私有void隐藏项(菜单菜单,布尔可见)
    {
    对于(int i=0;i
  • 检测导航抽屉滑动的程度:

         mDrawerLayout.setDrawerListener(new DrawerListener(){
                        float mPreviousOffset = 0f;
    
            @Override
            public void onDrawerClosed(View arg0) {
                             super.onDrawerClosed(arg0);
                             shouldGoInvisible = false;
                             invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
    
            @Override
            public void onDrawerOpened(View arg0) {
                             super.onDrawerOpened(arg0);
                             shouldGoInvisible = true;
                             invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
    
            @Override
            public void onDrawerSlide(View arg0, float slideOffset) {
                 super.onDrawerSlide(arg0, slideOffset);
                 if(slideOffset > mPreviousOffset && !shouldGoInvisible){
                    shouldGoInvisible = true;
                    invalidateOptionsMenu();
                }else if(mPreviousOffset > slideOffset && slideOffset < 0.5f && shouldGoInvisible){
                    shouldGoInvisible = false;
                    invalidateOptionsMenu();
                }
                mPreviousOffset = slideOffset;
    
    
            }
    
            @Override
            public void onDrawerStateChanged(int arg0) {
                // or use states of the drawer to hide/show the items
    
            }});
    
    mDrawerLayout.setDrawerListener(新的DrawerListener(){
    浮点mPreviousOffset=0f;
    @凌驾
    公共无效onDrawerClosed(视图arg0){
    super.onDrawerClosed(arg0);
    shouldGoInvisible=false;
    InvalidateOptions SMenu();//创建对OnPrepareOptions SMenu()的调用
    }
    @凌驾
    已打开的公共void onDrawerOpened(视图arg0){
    super.onDrawerOpened(arg0);
    shouldGoInvisible=true;
    InvalidateOptions SMenu();//创建对OnPrepareOptions SMenu()的调用
    }
    @凌驾
    绘图滑块上的公共无效(视图arg0,浮动滑块偏移){
    super.onDrawerSlide(arg0,slideOffset);
    如果(滑动偏移>MPPreviousOffset&&!应可见){
    shouldGoInvisible=true;
    无效操作菜单();
    }否则,如果(mPreviousOffset>slideOffset&&slideOffset<0.5f&&shouldGoInvisible){
    shouldGoInvisible=false;
    无效操作菜单();
    }
    MPPreviousOffset=滑动偏移;
    }
    @凌驾
    公共无效onDrawerStateChanged(int arg0){
    //或者使用抽屉的状态隐藏/显示项目
    }});
    

    注意:
    应该是可见的
    是类字段

    我半同意尼古拉的观点,但只要在抽屉状态发生变化时更新图标就足够了

    创建全局变量以跟踪抽屉状态:

    private int mDrawerState;
    
    设置新的抽屉式储物箱:

    mDrawerLayout.setDrawerListener(new DrawerListener() {
    
      @Override
      public void onDrawerStateChanged(int state) {
        mDrawerState = state;
        invalidateOptionsMenu();
      }
    
      @Override
      public void onDrawerSlide(View view, float slide) {
        // TODO Auto-generated method stub
      }
    
      @Override
      public void onDrawerOpened(View view) {
        // TODO Auto-generated method stub
      }
    
      @Override
      public void onDrawerClosed(View view) {
        // TODO Auto-generated method stub
      }
    });
    
    更新菜单可见性:

    boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawer);
    for(int i=0;i<menu.size();i++){
      // If the drawer is moving / settling or open do not draw the icons
      menu.getItem(i).setVisible(mDrawerState!=DrawerLayout.STATE_DRAGGING &&
          mDrawerState!=DrawerLayout.STATE_SETTLING && !drawerOpen);
    }
    
    boolean-drawerlayout=mDrawerLayout.isDrawerOpen(mDrawer);
    
    对于(int i=0;i如果要隐藏所有菜单项,只需使用:

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
    
        return showActionBarMenu; // boolean value, set it in drawer listeners as class variable
    }
    

    然后,您不需要看到每个菜单项。

    如果您想在抽屉进入屏幕后立即覆盖操作栏,并在抽屉不再可见时恢复操作栏(截至2014年3月20日,Gmail的行为正是如此),您可以使用以下代码:

    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
        R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
    
      @Override
      public void onDrawerStateChanged(int newState) {
        super.onDrawerStateChanged(newState);
    
        boolean isOpened = mDrawerLayout.isDrawerOpen(mDrawerList);
        boolean isVisible = mDrawerLayout.isDrawerVisible(mDrawerList);
    
        if (!isOpened && !isVisible) {
          if (newState == DrawerLayout.STATE_IDLE) {
            // drawer just hid completely
            restoreActionBar();
          } else {
            // } else if (newState == DrawerLayout.STATE_SETTLING) {
            // drawer just entered screen
            overrideActionBar();
          }
        }
      }
    
      private void restoreActionBar() {
        getSupportActionBar().setTitle(mTitle);
        supportInvalidateOptionsMenu();
      }
    
      private void overrideActionBar() {
        getSupportActionBar().setTitle(mDrawerTitle);
        supportInvalidateOptionsMenu();
      }
    };
    
    // Set the drawer toggle as the DrawerListener
    mDrawerLayout.setDrawerListener(mDrawerToggle);
    
    根据需要修改
    restoreActionBar()
    overrideActionBar()
    方法

    不需要区分滑动和主页按钮,也不需要测量滑动长度

    变异 如果不想引用抽屉列表视图,请使用以下代码:

        boolean isOpened = mDrawerLayout.isDrawerOpen(GravityCompat.START);
        boolean isVisible = mDrawerLayout.isDrawerVisible(GravityCompat.START);
    
    您可能希望使用
    GravityCompat.END
    ,这取决于您在XML布局中指定的内容

    编辑-有关操作 上面的示例没有隐藏与导航抽屉下的内容相关的操作栏项目。要这样做或在抽屉可见时显示不同的图标集,您必须跟踪抽屉是手动打开还是关闭的

    除上述代码外,通过正确的保存/还原状态处理声明
    专用布尔值mdrawerible=false
    。 然后修改
    mDrawerToggle
    内部方法,如下所示:

      private void restoreActionBar() {
        getSupportActionBar().setTitle(mTitle);
        mDrawerVisible = false;
        supportInvalidateOptionsMenu();
      }
    
      private void overrideActionBar() {
        getSupportActionBar().setTitle(mDrawerTitle);
        mDrawerVisible = true;
        supportInvalidateOptionsMenu();
      }
    

    最后,在
    onCreateOptions菜单中
    膨胀不同的菜单资源,或者在
    onPrepareOptions菜单中
    根据
    mdrawerible
    的值显示/隐藏不同的操作,我接受了@Laurence Dawson的答案,并对其进行了简化。此解决方案不需要使用任何类成员

    onCreate()期间执行此代码:

    并覆盖此方法:

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
    
        DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        boolean actionsVisibility = !drawerLayout.isDrawerVisible(Gravity.START);
    
        for(int i=0;i<menu.size();i++){
            menu.getItem(i).setVisible(actionsVisibility);
        }
    
        return super.onPrepareOptionsMenu(menu);
    }
    
    @覆盖
    公共布尔值OnPrepareOptions菜单(菜单){
    抽屉布局抽屉布局=(抽屉布局)findViewById(R.id.drawer\U布局);
    布尔操作可视性=!drawerLayout.isDrawervible(Gravity.START);
    
    对于(int i=0;i我对这个问题有一个更好的解决方案:

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if (navigationDrawerFragment.isDrawerOpen()) {
            menu.clear();
        }
        return super.onPrepareOptionsMenu(menu);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!navigationDrawerFragment.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.
            showLocalContextActionBar();
            return false;
        }
        return super.onCreateOptionsMenu(menu);
    }
    

    我有不同的代码,但解决方案相同:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        hideMenuItems(menu, !mShouldGoInvisible);
        return super.onCreateOptionsMenu(menu);
    }
    private void hideMenuItems(Menu menu, boolean visible){
        for(int i = 0; i < menu.size(); i++){
    
            menu.getItem(i).setVisible(visible);
        }
    }
    

    是的,这基本上就是我正在做的。问题是,直到抽屉完全打开,代码才会被调用,而不是像Gmail中一样,抽屉一打开,甚至一点点。我在onDrawerOpen()和onDrawerClose()中调用SupportInvalidateOptions菜单()我的ActionBarDrawerToggle对象。@Synergy807我已经测试过了,它可以像你期望的那样完美地工作。无论抽屉在任何方向上滑动多少次,它都会隐藏抽屉。谢谢你的帮助!onDrawerSlide和OnDrawerState方法在我需要的地方改变了。应该看到的是一个类字段。你能展示它是如何定义的吗?
    private boolean shouldGoInvisible=false;
    谢谢,这与我最终的做法非常相似!事实上,在进一步调查之后,我发现使用状态并不太有效,至少在我的实现中是如此。如果你只是
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        hideMenuItems(menu, !mShouldGoInvisible);
        return super.onCreateOptionsMenu(menu);
    }
    private void hideMenuItems(Menu menu, boolean visible){
        for(int i = 0; i < menu.size(); i++){
    
            menu.getItem(i).setVisible(visible);
        }
    }
    
     @Override
    public void onNavigationDrawerListener(boolean opened, int position) {
    
        if (opened){
            mShouldGoInvisible = true;
            invalidateOptionsMenu();
    
        } else {
            mShouldGoInvisible = false;
            invalidateOptionsMenu();
        }
    }