Prevent DrawerLayout from handling touches in content area
Asked Answered
C

2

1

Normally when pressing on the content area of the DrawerLayout, the drawer will close and the touch is consumed. Is there a way to prevent this and pass the touch event on to the content area?

Thanks!

Claire answered 4/9, 2013 at 4:37 Comment(0)
E
2

Inspired by the answer given by guy_m, I adapted his proposals and suggest the following extension of DrawerLayout. Again, this solution is by overriding onInterceptTouchEvent().

The logic of the overriding method is fairly simple:

  • Whenever a touch event occurs off the drawer view (the slideable part of the DrawerLayout), we return false. This means that DrawerLayout does neither intercept nor care about this and any further touch events of that gesture, and any such events are handled by the child view(s) of the DrawerLayout.
  • On the other hand, when an event occurs inside the drawer view, we call super.onInterceptTouchEvent() and let this method decide if the event should be intercepted and/or how it should be handled. This lets us slide the drawer in and out as with the original DrawerLayout, as long as the slide/touch gesture happens on the drawer view.

The following example of an overridden onInterceptTouchEvent() method is for a DrawerLayout whose drawer view is located on the right of the screen (android:gravity="right"). However, it should be obvious how to adapt the code to work for a standard left-placed drawer view as well.

public class CustomDrawerLayout extends DrawerLayout
{

    @Override
    public boolean onInterceptTouchEvent( MotionEvent event )
    {
        final View drawerView = getChildAt( 1 );
        final ViewConfiguration config = ViewConfiguration.get( getContext() );

        // Calculate the area on the right border of the screen on which
        // the DrawerLayout should always intercept touch events.
        // In case the drawer is closed, we still want the DrawerLayout
        // to respond to touch/drag gestures there and reopen the drawer!
        final int rightBoundary = getWidth() - 2 * config.getScaledTouchSlop();

        // If the drawer is opened and the event happened
        // on its surface, or if the event happened on the
        // right border of the layout, then we let DrawerLayout
        // decide if it wants to intercept (and properly handle)
        // the event.
        // Otherwise we don't let DrawerLayout to intercept,
        // letting its child views handle the event.
        return ( isDrawerOpen( drawerView ) && drawerView.getLeft() <= event.getX()
                || rightBoundary <= event.getX() )
                && super.onInterceptTouchEvent( event );
    }
...
}
Elutriate answered 7/10, 2017 at 16:2 Comment(3)
Can you provide some explanation on why this solves the problem?Chanty
Sorry, I typed an explanation before, but somehow it got lost on posting. I'll edit the answer.Elutriate
This is probably a better solution than my hack.Claire
C
6

I ended up modifing DrawerLayout.

In the method onInterceptTouchEvent(MotionEvent ev) you'll have to prevent interceptForTap being set to true. One way is to remove the following conditional.

if (mScrimOpacity > 0 &&
    isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {
    interceptForTap = true;
}

That will allow touches to "fall through".

To have the drawer not close you can set the drawer lock mode to LOCK_MODE_LOCKED_OPEN.

Claire answered 6/9, 2013 at 4:14 Comment(2)
how did you modify DrawerLayout?Swanner
Download the source, modify it, and add it to your project.Claire
E
2

Inspired by the answer given by guy_m, I adapted his proposals and suggest the following extension of DrawerLayout. Again, this solution is by overriding onInterceptTouchEvent().

The logic of the overriding method is fairly simple:

  • Whenever a touch event occurs off the drawer view (the slideable part of the DrawerLayout), we return false. This means that DrawerLayout does neither intercept nor care about this and any further touch events of that gesture, and any such events are handled by the child view(s) of the DrawerLayout.
  • On the other hand, when an event occurs inside the drawer view, we call super.onInterceptTouchEvent() and let this method decide if the event should be intercepted and/or how it should be handled. This lets us slide the drawer in and out as with the original DrawerLayout, as long as the slide/touch gesture happens on the drawer view.

The following example of an overridden onInterceptTouchEvent() method is for a DrawerLayout whose drawer view is located on the right of the screen (android:gravity="right"). However, it should be obvious how to adapt the code to work for a standard left-placed drawer view as well.

public class CustomDrawerLayout extends DrawerLayout
{

    @Override
    public boolean onInterceptTouchEvent( MotionEvent event )
    {
        final View drawerView = getChildAt( 1 );
        final ViewConfiguration config = ViewConfiguration.get( getContext() );

        // Calculate the area on the right border of the screen on which
        // the DrawerLayout should always intercept touch events.
        // In case the drawer is closed, we still want the DrawerLayout
        // to respond to touch/drag gestures there and reopen the drawer!
        final int rightBoundary = getWidth() - 2 * config.getScaledTouchSlop();

        // If the drawer is opened and the event happened
        // on its surface, or if the event happened on the
        // right border of the layout, then we let DrawerLayout
        // decide if it wants to intercept (and properly handle)
        // the event.
        // Otherwise we don't let DrawerLayout to intercept,
        // letting its child views handle the event.
        return ( isDrawerOpen( drawerView ) && drawerView.getLeft() <= event.getX()
                || rightBoundary <= event.getX() )
                && super.onInterceptTouchEvent( event );
    }
...
}
Elutriate answered 7/10, 2017 at 16:2 Comment(3)
Can you provide some explanation on why this solves the problem?Chanty
Sorry, I typed an explanation before, but somehow it got lost on posting. I'll edit the answer.Elutriate
This is probably a better solution than my hack.Claire

© 2022 - 2024 — McMap. All rights reserved.