22

我有一个主要活动,它带有两个导航抽屉。左边的总是可访问的,但右边的用于显示一些必要的列表和执行某些操作。当我将某些片段加载到FrameLayout活动的中心时,它们具有需要打开右抽屉并选择项目的操作。所有这一切都很好,但我想确保当按下后退按钮或在抽屉外单击屏幕时,抽屉关闭、锁定并删除加载的片段。我还应该提到,这个右边的抽屉里有一个FrameLayout并依赖于碎片。

在我的主要活动中,这就是我所说的:

@Override       
public void onBackPressed(){
    Log.d(TAG, "onBackPressed() called");
    if(drawerLayoutRight.isDrawerOpen(drawerFrameRight)){
        Log.d(TAG, "----------------------");
        drawerLayoutRight.closeDrawer(drawerFrameRight);
        drawerLayoutRight.setDrawerLockMode(1, drawerFrameRight);
        ExcerciseList fragment = (ExcerciseList) getFragmentManager().findFragmentById(R.id.right_drawer);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.remove(fragment).commit();
    } else {        
        super.onBackPressed();
    }
}

我也试过:

public boolean onKeyDown(int keyCode, KeyEvent event){
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        Log.d(TAG, "onKeyDown called");
        return true;
    }

    return super.onKeyDown(keyCode, event);
}

但这也没有奏效。每当我单击后退按钮时,抽屉都会关闭,但这些方法都不会被调用。但是一旦抽屉关闭,如果按下后退按钮,这些方法将被调用。我还想知道是否有人知道处理抽屉外点击的简单方法。我想我可以进行自定义DrawerLayout并覆盖drawerClose()或检查在触摸事件上单击的坐标。只是好奇是否有人有更简单的方法。

4

8 回答 8

72

将此行放入您的代码中:

mDrawerLayout.setFocusableInTouchMode(false);

onBackPressed()然后,当您按下后退按钮时,它会调用您的覆盖。

于 2013-09-25T05:58:02.520 回答
2

在 Force EditText 的问题中引用我自己的话,以便在按下后失去焦点

“根据我的经验,onBackPressed()(至少是活动中的默认@Override)在按下后退按钮关闭键盘时通常不会触发。据我所知,它只会在后退按钮启动完成时触发() 关于当前活动。”

这可能以相同的方式应用于导航抽屉。

这很可能是由于抽屉打开时当前“活动”不在焦点上(与软键盘相同),因此没有调用 @Override 后退按钮。

于 2013-08-17T22:19:03.103 回答
1

正如@Alex Vasilkov 指出的那样,这个问题似乎与该drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);方法有关。

上面的建议都没有对我有用。所以我想写我自己的解决方案。我挖掘了 DrawerLayout 类的源代码并尝试了覆盖onKeyDownonKeyUp方法,但是如果锁定模式为LOCK_MODE_LOCKED_CLOSED. 我认为这是一个错误。

所以在我的情况下,我只需要锁定左侧的导航抽屉,而不是右侧的。最后我调用了drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.START);这个方法来锁定我的左侧导航抽屉,而不是调用drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);这个方法,这会锁定两个抽屉并导致这个后退按钮错误。

总而言之,drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);以某种方式禁用后退按钮单击。也许只有当您有两个导航抽屉时。

于 2014-12-19T06:08:35.463 回答
1

只需简单地覆盖您的活动或抽屉布局,就可以了。

@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (KeyEvent.KEYCODE_BACK == keyCode
            && mDrawerLayout != null
            && mDrawerLayout.isDrawerOpen(leftDrawerView)) {
        KeyEventCompat.startTracking(event);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (KeyEvent.KEYCODE_BACK == keyCode
            && !event.isCanceled()
            && mDrawerToggle != null
            && mDrawerLayout.isDrawerOpen(leftDrawerView)) {
        mDrawerLayout.closeDrawers();
        return true;
    }
    return super.onKeyUp(keyCode, event);
}
于 2014-09-21T18:32:33.843 回答
1

我能够通过使用来解决我的问题DrawerLayout.DrawerListener。这在我的情况下有效,因为当按下后退按钮时,即使onBackPressed()没有调用该方法,抽屉仍在关闭。

@MH 说,“如果抽屉打开,DrawerLayout(我假设这就是你正在使用的)将消耗后退按钮事件。”

尽管在文档中我找不到明确提及这一点;这里提到了后退按钮。不幸的是,它没有多大帮助。

@MH 所说的解释了为什么onBackPressed()在打开抽屉时没有调用它,以及为什么在它关闭时调用它。

drawerLayoutRight.setDrawerListener(this);

drawerLayoutRight一个在哪里DrawerLayout。我的听众看起来像这样:

@Override
public void onDrawerClosed(View arg0) {
    if(drawerLayoutRight.getDrawerLockMode(drawerFrameRight)!= 1){
        drawerLayoutRight.setDrawerLockMode(1, drawerFrameRight);
    }
    ExcerciseList fragment = (ExcerciseList) getFragmentManager().findFragmentById(R.id.right_drawer);
    if (fragment != null) {
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.remove(fragment).commit();
    }
}

onDrawerOpened()onDrawerSlide()并且onDrawerStateChanged()都是空的。我只有一个抽屉在使用监听器,所以我不必检查视图。

于 2013-08-18T14:20:24.127 回答
1

添加此行后退按钮将设法关闭DrawerLayout

mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 
于 2015-06-22T04:51:59.710 回答
1

我在片段中的空列表有一个非常相似的问题(当列表为空时不会响应后退按钮按下),这里提到的一些解决方案帮助我解决了我的问题。

导致“onBackPressed()”问题的片段:

<TextView
   android:id="@android:id/empty"
   ... />
<ListView
   android:id="@android:id/list"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

问题类似,当适配器返回的列表为空(@android:id/empty)时,第一个视图(TextView)似乎并没有被 Android“视为”为可聚焦/聚焦的视图(而第二个视图 - ListView - 是)。

因此,按下后退按钮不会被当前显示的视图注册,也不会被片段中的自定义代码捕获(而是直接关闭活动)。

在我的情况下,将以下内容添加到 onCreateView 解决了我的问题(并且即使列表为空,片段也允许按下后退按钮):

    View view = inflater.inflate(R.layout.fragment_content, container, false);
    view.setFocusableInTouchMode(true);
    view.requestFocus();
于 2015-08-03T08:43:44.113 回答
-2

我知道这有点晚了,但仍然......这个答案会帮助其他人

@Override
public void onBackPressed()
{
  if (mDrawerLayout.isOpen())
  mDrawerLayout.close();
else
  super.onBackPressed();
}
于 2015-04-22T14:07:38.150 回答