Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How do I keep DrawerLayout from passing touch events to the underlying view

I am using the Support library's DrawerLayout in my app. I noticed that, when I click on an empty area in my Drawer view, the underlying View (containing a ListView) receives the Touch event and reacts to it.

The onInterceptTouchEvent method of the DrawerLayout looks like this:

@Override public boolean onInterceptTouchEvent(MotionEvent ev) {     final int action = MotionEventCompat.getActionMasked(ev);      // "|" used deliberately here; both methods should be invoked.     final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) |             mRightDragger.shouldInterceptTouchEvent(ev);      boolean interceptForTap = false;      switch (action) {         case MotionEvent.ACTION_DOWN: {             final float x = ev.getX();             final float y = ev.getY();             mInitialMotionX = x;             mInitialMotionY = y;             if (mScrimOpacity > 0 &&                     isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {                 interceptForTap = true;             }             mDisallowInterceptRequested = false;             mChildrenCanceledTouch = false;             break;         }          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;         }          case MotionEvent.ACTION_CANCEL:         case MotionEvent.ACTION_UP: {             closeDrawers(true);             mDisallowInterceptRequested = false;             mChildrenCanceledTouch = false;         }     }      return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch; } 

My view with the DrawerLayout:

<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">      <FrameLayout             android:id="@+id/content"             android:layout_width="wrap_content"             android:layout_height="wrap_content"/>      <FrameLayout             android:id="@+id/sidebar_container"             android:layout_width="300dp"             android:layout_height="match_parent"             android:layout_gravity="left"/>  </android.support.v4.widget.DrawerLayout> 

What can I do, (if possible without extending the DrawerLayout class) to prevent this behaviour? As long as the drawer is open, I want no click events to reach the background view.

like image 313
janoliver Avatar asked Sep 15 '13 11:09

janoliver


1 Answers

Set clickable to true on the drawer - it'll consume the touch.

<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">      <FrameLayout         android:id="@+id/content_view"         android:layout_width="wrap_content"         android:layout_height="wrap_content"/>      <FrameLayout         android:id="@+id/drawer_view"         android:layout_width="300dp"         android:clickable="true"         android:importantForAccessibility="no"         android:layout_height="match_parent"         android:layout_gravity="left"/>  </android.support.v4.widget.DrawerLayout> 

I added android:importantForAccessibility="no" because marking the drawer as interactive (clickable or focusable) will make the entire drawer visible to accessibility services like TalkBack.

This is not what you want (usually) - more often, items inside the drawer should be accessible to the services.

This attribute is only available on API 16+.

like image 114
ataulm Avatar answered Sep 21 '22 10:09

ataulm