【问题标题】:Event before DrawerLayout opensDrawerLayout 打开前的事件
【发布时间】:2013-07-20 17:23:19
【问题描述】:

在我看来,DrawerLayout 实现缺少一件事:在抽屉打开之前触发的事件。

drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
  public void onDrawerClosed(View view) {
    //...
  }

  public void onBeforeDrawerOpened(View drawerView) {
    //...
  }

  public void onDrawerOpened(View drawerView) {
    //...
  }
};

需要它的原因是设置抽屉项的状态,例如选择、启用和类似的菜单项。将其放入 onDrawerOpened() 回调中有点工作,但在打开后更改菜单外观看起来并不正确。

我的第一个想法是扩展 ActionBarDrawerToggle 并提供新事件。我应该重新发明轮子 :-) 还是有人已经这样做了?

【问题讨论】:

  • 附录:我想到在newState == DrawerLayout.STATE_DRAGGING 时使用onDrawerStateChanged(),但它似乎是双向调用的,抽屉关闭时也是如此。

标签: android navigation-drawer


【解决方案1】:

此链接可以帮助您解决问题。 How to detect that the DrawerLayout started opening?

使用onDrawerStateChanged(int newState)回调

你需要听STATE_SETTLING states - 这个 state 是 每当抽屉开始移动(打开或关闭)时报告。所以 一旦你看到这个状态 - 检查抽屉现在是否打开并采取行动 相应地:

    mDrawerToggle = new ActionBarDrawerToggle(
        this,                 
        mDrawerLayout,        
        R.drawable.ic_drawer,  
        R.string.drawer_open,  
        R.string.drawer_close  
) {
    @Override
    public void onDrawerStateChanged(int newState) {
        if (newState == DrawerLayout.STATE_SETTLING) {
            if (!isDrawerOpen()) {
                // starts opening
                getActionBar()
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            } else {
                // closing drawer
                getActionBar()
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            }
            invalidateOptionsMenu();
        }
    }
};
mDrawerLayout.setDrawerListener(mDrawerToggle);

【讨论】:

    【解决方案2】:

    当我遇到这个问题时,我在谷歌上找到了这个,但在任何地方都没有找到确切的答案,所以我决定发布完整的答案。希望它可以节省一些时间。

    我发现的最佳解决方案是使用 isDrawerOpen 方法监视抽屉状态并确定它是打开还是关闭。请务必将重力设置为与打开/关闭抽屉时使用的重力相匹配。

    DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    // ...
    ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
    R.drawable.ic_playlist, R.string.drawer_open, R.string.drawer_close) {
        public void onDrawerStateChanged(int newState) {
            if(newState == DrawerLayout.STATE_DRAGGING){
                if(mDrawerLayout.isDrawerOpen(Gravity.LEFT)){
                    //closing
    
                }else{
                    //opening
    
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      来自 Lenny 和 Fred 对 kotlin 的回答:

          var toggle = object : ActionBarDrawerToggle(this,
          drawer_layout, toolbar, R.string.drawer_open, R.string.drawer_close) {
      
              override fun onDrawerStateChanged(newState: Int) {
                  super.onDrawerStateChanged(newState)
      
                  if(newState == DrawerLayout.STATE_SETTLING){
                      if(drawer_layout.isDrawerOpen(Gravity.LEFT)){
                          //closing
                      }else{
                          //opening
                      }
                  }
              }
          }
          drawer_layout.addDrawerListener(toggle)
          toggle.syncState()
      

      【讨论】:

        【解决方案4】:

        接受的答案中推荐的setDrawerListener 方法现在是deprecated。执行此操作的新方法是使用 addDrawerListener 方法。

        在 Kotlin 中

        1. 初始化DrawerLayout 视图

          val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)

        2. 在您的主要活动中,创建一个内部类,它是DrawerLayout.DrawerListener 的子类。 DrawerLayout 类实现了 DrawerListener 接口。您可以在 onDrawerSlide 中跟踪不断变化的抽屉位置,并确定抽屉是打开还是关闭:

          inner class CustomDrawer : DrawerLayout.DrawerListener{
            override fun onDrawerStateChanged(newState: Int) {
            }
          
          var last: Float = 0f
          
          override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
              imm.hideSoftInputFromWindow(drawerView?.getWindowToken(), 0)
          
              var opening: Boolean = slideOffset>last
              var closing: Boolean = slideOffset<last
          
              if(opening) {
                  Log.i("Drawer","opening")
                  Log.d("Last",last.toString())
              } else if(closing) {
                  Log.i("Drawer","closing")
                  Log.d("Last",last.toString())
              } else {
                  Log.i("Drawer","doing nothing")
                  Log.d("Last",last.toString())
              }
          }
          
          override fun onDrawerClosed(drawerView: View) {
          
            }
          
          override fun onDrawerOpened(drawerView: View) {
          
            }
          }
          
        3. 将你的自定义 DrawerListener 添加到 DrawerLayout(我把它放在 onCreate 方法中)

          var drawerListener = CustomDrawer()
          drawerLayout.addDrawerListener(drawerListener)
          

        【讨论】:

          猜你喜欢
          • 2013-05-24
          • 1970-01-01
          • 2014-06-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-24
          • 2014-06-11
          相关资源
          最近更新 更多