如何防止通过手势打开 NavigationDrawer,但允许从支持设计库 23.1.1.1 中的汉堡包图标

How to prevent NavigationDrawer from being opened by gesture, but allow from hamburger icon in Support Design Library 23.1.1.1

我有一个 ViewPager,其中页面包含对滑动动作做出反应的图表视图。因此,我求助于通过从屏幕边缘滑动来更改页面。但这给我留下了一个问题,即这也是打开 NavigationDrawer 的手势。

到目前为止,我使用以下代码来实现此目的:

protected override void OnCreate(Bundle savedInstanceState)
{
  base.OnCreate(savedInstanceState);

  SetContentView(GetLayoutId());

  Toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
  if (Toolbar != null)
  {
    // set this flag so the colors colorPrimaryDark and android:statusBarColor have an effect
    // setting android:statusBarColor to transparent causes the drawer to be dran underneath a translucent status bar
    Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);

    // make the toolbar the replacement of the action bar
    SetSupportActionBar(Toolbar);
  }

  // add the hamburger icon
  m_DrawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
  var actionBarDrawerToggle = new ActionBarDrawerToggle(this, m_DrawerLayout, Toolbar, Resource.String.empty, Resource.String.empty);
  m_DrawerLayout.AddDrawerListener(actionBarDrawerToggle);

  // make sure the drawer can't be opened by swiping, to do this we set the lock mode to closed
  // but if we just do this, it can't be closed by swiping either, so set the lock mode to unlocked when the drawer is opened, and locked again when it's closed
  m_DrawerLayout.DrawerOpened += (object sender, DrawerLayout.DrawerOpenedEventArgs e) =>
  {
    m_DrawerLayout.SetDrawerLockMode(DrawerLayout.LockModeUnlocked);
  };
  m_DrawerLayout.DrawerClosed += (object sender, DrawerLayout.DrawerClosedEventArgs e) =>
  {
    m_DrawerLayout.SetDrawerLockMode(DrawerLayout.LockModeLockedClosed);
  };
  m_DrawerLayout.SetDrawerLockMode(DrawerLayout.LockModeLockedClosed);

  //calling sync state is necessay or else the hamburger icon wont show up
  actionBarDrawerToggle.SyncState();
}

它按预期工作,直到我更新到 Android 支持设计库 23.1.1.1,现在将锁定模式设置为关闭还可以防止通过点击汉堡图标打开菜单。

查看 ActionBarDrawerToggle class 最新版本的源代码,这似乎确实是新的预期行为。它的 toggle() 方法现在看起来像这样:

private void toggle() {
    int drawerLockMode = mDrawerLayout.getDrawerLockMode(GravityCompat.START);
    if (mDrawerLayout.isDrawerVisible(GravityCompat.START)
        && (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_OPEN)) {
        mDrawerLayout.closeDrawer(GravityCompat.START);
    }
    else if (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
        mDrawerLayout.openDrawer(GravityCompat.START);
    }
}

而之前它只是检查了抽屉的 opened/closed 状态。

这很不幸,因为它现在需要一个解决方法来实现旧的行为。也许最简单的事情就是恢复到旧版本的支持库。但是,如果您想保留最新版本,一种可能的解决方案如下。

首先从 ActionBarDrawerToggle 构造函数调用中删除 Toolbar 参数。

actionBarDrawerToggle = new ActionBarDrawerToggle(this, 
                                                  m_DrawerLayout, 
                                                  Resource.String.empty,
                                                  Resource.String.empty);

这将导致 ActivityOnOptionsItemSelected() 方法在单击切换时触发,因为您已将 Toolbar 设置为支持 ActionBar。我们还需要调用 SupportActionBar.SetDisplayHomeAsUpEnabled(true) 来实际显示切换,因为 ActionBarDrawerToggle class 与 ActionBar 的交互方式与与 Toolbar 的交互方式有所不同,关于他们的 child Views.

ActivityOnOptionsItemSelected() 方法中,我们在调用 toggle 自己的 OnOptionsItemSelected() 方法之前简单地解锁抽屉,该方法处理抽屉的打开和关闭。

public override bool OnOptionsItemSelected (IMenuItem item)
{       
    switch (item.ItemId)
    {
        case Android.Resource.Id.Home:
            m_DrawerLayout.SetDrawerLockMode(DrawerLayout.LockModeUnlocked);
            actionBarDrawerToggle.OnOptionsItemSelected(item);

            return true;
        ...
    }
    ... 
}

您的 actionBarDrawerToggle 需要成为您的 Activity 的一个字段,您可以删除 DrawerOpened 处理程序。