Android:导航抽屉打开时未调用onBackPressed()

时间:2013-08-17 22:06:06

标签: android

我有一个主要活动,有两个导航抽屉。左边的一个始终可访问,但右边的一个用于显示一些必要的列表并执行某些操作。当我将某些片段加载到活动的中心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()或检查点击触摸事件的坐标。只是好奇,如果有人有更简单的方法。

8 个答案:

答案 0 :(得分:72)

将此行放入您的代码中:

mDrawerLayout.setFocusableInTouchMode(false);

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

答案 1 :(得分:2)

Force EditText to lose focus when back pressed

的问题引用自己的话

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

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

这很可能是因为抽屉打开时当前的“活动”不在焦点(与SoftKeyboard相同),因此不会调用@Override后退按钮。

答案 2 :(得分:1)

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

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

虽然在文档中我找不到明确的提及;有一些提到后退按钮here。不幸的是它没有多大帮助。

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

drawerLayoutRight.setDrawerListener(this);

drawerLayoutRightDrawerLayout的位置。我的听众看起来像这样:

@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()都是空的。我的抽屉中只有一个使用了监听器,所以我不必检查视图。

答案 3 :(得分: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);
}

答案 4 :(得分: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);会以某种方式禁用后退按钮。也许只有你有两个导航抽屉。

答案 5 :(得分:1)

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

mDrawerLayout.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 

答案 6 :(得分: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();

答案 7 :(得分:-2)

我知道这有点晚了但是......这个答案会帮助别人

@Override
public void onBackPressed()
{
  if (mDrawerLayout.isOpen())
  mDrawerLayout.close();
else
  super.onBackPressed();
}