使用示例的Android Navigation Drawer bug

时间:2013-08-04 14:57:41

标签: android sample navigation-drawer

我正在尝试根据我的应用实现导航抽屉模式。我从here下载了示例代码并运行了它,抽屉工作的时间有90%,但有时当我尝试打开它时抽屉卡住了。我有办法复制情况,但并不总是有效。我所做的是:

1-按原样运行示例代码 2-将手指放在左边缘以使抽屉窥视 3-松开手指并将其按在主片上 4-尝试照常打开抽屉

有时,无论您向右滑动多少手指以更多地打开抽屉,抽屉都会卡在偷看模式上。有人有/解决了这个问题吗?

3 个答案:

答案 0 :(得分:19)

我遇到了你提到的类似问题。我在相对布局(FILL_PARENT)中有一个列表视图。每当列表视图中的内容较少,并且当我在列表视图外部的区域中拖动时,导航抽屉就会被击中。为相对布局设置android:clickable="true"解决了问题。希望这可能有所帮助。

答案 1 :(得分:16)

要澄清Viji的答案,如果您使用的是提供的导航抽屉示例:

<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         The drawer is given a fixed width in dp and extends the full height of
         the container. A solid background is used for contrast
         with the content view. -->
    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

android:clickable="true"添加到FrameLayout似乎可以解决问题。

答案 2 :(得分:0)

两个解决方案。

  1. 设置android:clickable
  2. 复制抽屉式布局的源代码并删除peekDrawer函数以禁用此功能

让我解释一下此错误的原因。

DrawerLayout的三种状态 STATE_IDLE,STATE_DRAGGING,STATE_SETTLING

ACTION_DOWN-> onEdgeTouched will be triggered if it is on the edge, DrawerLayout will trigger peekDrawer after 120ms

PeekDrawer实际上将DrawerLayout的状态更改为STATE_SETTLING,然后让Drawer滚动到指定位置。然后将状态设置为“空闲”。

ACTION_MOVE-> 

If the current state is DRAGGING, drag captureView

If the current state is not DRAGGING, it will try to execute tryCaptureViewForDrag to reset the state to DRAGGING.

And at the same time, it will also determine whether a new edge gesture is triggered (emphasis !!)

If a new edge gesture was dete, it will invoke onEdgeDragStared
and DrawerLayout will go to captureView to captrue the drawer

如何修复此错误?

  • 首先点击边缘以调用120ms延迟功能peekDrawer
  • 在调用peekDrawer之前,触发onEdgeDragStared让抽屉布局捕获抽屉,将dragState设置为STATE_DRAGGING
  • 120毫秒后,如果您的手指仍在抽屉布局想要窥视的区域,则dragState将设置为SETTLING
  • 在将抽屉窥视到目的地之前,将手指快速移到窥视末端之前的那个区域,因为状态为SETTLING,所以抽屉不会跟随您的手指,在SETTLING之后,状态将设置为IDLE
  • 现在您的手指完全脱离了抽屉,状态为“空闲”,因此您无法再拖动视图

因此,解决方案是停止peekDrawer 实际上,抽屉布局已解决了此问题。

    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (action) {

            case MotionEvent.ACTION_MOVE: {
                // If we cross the touch slop, don't perform the delayed peek for an edge touch.
                if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
                    mLeftCallback.removeCallbacks();
                    mRightCallback.removeCallbacks();
                }
                break;
            }

        }

        return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
    }

如果子级是可单击的,则子级将使用该事件,onInterceptTouchEvent将调用多次。并在移动时删除peekDraw。