Disable DrawerLayout's scrim touch gesture

2019-03-02 06:44发布

enter image description here

I need to disable touch gesture on the scrim (the red highlighted part). I want to dismiss the drawer only with the swipe.

The issue is that when the drawer layout is open and I need to select an element from the ListView below the red highlighted part, what's happend is that the drawer get closed and only at this point I can select an element from the ListView.

I need to select the element from the ListView directly, also when the Drawer is opened

3条回答
Emotional °昔
2楼-- · 2019-03-02 07:14

You have to create custom drawer for that like this

public class CustomDrawer extends DrawerLayout {



    public CustomDrawer(Context context) {
        super(context);

    }

    public CustomDrawer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    public CustomDrawer(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if(isDrawerOpen(Gravity.START)){
            if(event.getX() > getChildAt(1).getWidth()){
                return false;
            }
        }
        return super.onInterceptTouchEvent(event);
    }

}

Note : getChildAt(1) should be that child to whom you have given gravity as "start" and whose width determines the width of opening drawer.

I hope this should solve your problem

查看更多
Viruses.
3楼-- · 2019-03-02 07:29

just add android:clickable="true" to drawer menu.

查看更多
虎瘦雄心在
4楼-- · 2019-03-02 07:31

I asked an answered a question here:
How to vary between child and parent view group touch events

The parent (drawer) ontouchevent is being fired, rather than the child, listview.

I have also answered a similar problem here:

https://stackoverflow.com/a/28180281/3956566

You need to manage your touch events so it is handled by the child. You need to use an onInterceptTouchEvent and return false.

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    // returning false means the child will handle the touch event.
    return false;
}

You then manage you touchevent for the list view:

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // This method will only be called if the touch event was intercepted in 
    // onInterceptTouchEvent
    // TODO Select your listview item.

}

You can also determine what type of touch event is taking place eg, scrolling and determine whether the child or parent will manage the event.

Managing Touch Events in a ViewGroup

I've added this quote from here Understanding Android Input Touch Events System Framework (dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent, OnTouchListener.onTouch):

The root view starts dispatching the event down to its children. Let’s presume that we have this hierarchy:

A – ViewGroup1 (parent of B).
B – ViewGroup2 (parent of C).
C – View (child of B)
– receives a touch/tap/click. Now the root view will call A.dispatchTouchEvent(). Now the job of a ViewGroup.dispatchEvent() (not View.dispatchEvent()) is to find out all the child views and view groups whose bounds contain the touch point coordinates (using a hit testing algorithm). When it figures out a list of relevant children, it starts dispatching the events to them by calling their dispatchTouchEvent().

Here’s an important piece though. Before the dispatchTouchEvent() is called on the children, the A.dispatchTouchEvent() will first call A.onInterceptTouchEvent() to see if the view group is interested in intercepting the event and handling the subsequent gesture by itself (scrolling is a good use case where a fling on B should lead to scrolling on A). The method onInterceptTouchEvent() is only available on view groups (as they’re the one who can be parents/containers with the requirement to intercept touch events) that can sort of keep an eye on the event and hijack it by returning true. If it returns false then dispatching continues as usual, i.e., B.dispatchTouchEvent() (child) will be called. But on returning true, this is what’ll happen:

ACTION_CANCEL will be dispatched to all the children.
All the subsequent gesture events (till ACTION_UP/ACTION_CANCEL) will be consumed by the event listeners (OnTouchListener.onTouch()) if defined, else the event handler A.onTouchEvent() at A’s level.
A.onInterceptTouchEvent() itself will be never called again.

With this diagram:

diagram of touch event propagation

Let me know if you need more explanation.

查看更多
登录 后发表回答