Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DrawerLayout modify sensitivity?

The DrawerLayout default sensitivity is okay, but I would like to make it a little easier to do the left-to-right sliding gesture on the side of the screen to open the drawerlayout. I find it particiular difficult on tablets, but also on some phones.

I don't see any gesture or gesture controller references in the DrawerLayout page on the web API.. Has anyone seen something that will allow us to do this?

like image 932
Daniel Guillamot Avatar asked Jul 30 '13 08:07

Daniel Guillamot


1 Answers

For android.support.v4.widget.DrawerLayout I came up with a hack which allows you to expand the area where sliding gesture (stroke) can start, thus making sliding gesture easier.

Hack implementation:

    // assuming mDrawerLayout is an instance of android.support.v4.widget.DrawerLayout
    try {

        // get dragger responsible for the dragging of the left drawer
        Field draggerField = DrawerLayout.class.getDeclaredField("mLeftDragger");
        draggerField.setAccessible(true);
        ViewDragHelper vdh = (ViewDragHelper)draggerField.get(mDrawerLayout);

        // get access to the private field which defines
        // how far from the edge dragging can start
        Field edgeSizeField = ViewDragHelper.class.getDeclaredField("mEdgeSize");
        edgeSizeField.setAccessible(true);

        // increase the edge size - while x2 should be good enough,
        // try bigger values to easily see the difference
        int origEdgeSize = (int)edgeSizeField.get(vdh);
        int newEdgeSize = (int) (origEdgeSize * 2); 
        edgeSizeField.setInt(vdh, newEdgeSize);

    } catch (Exception e) {
        // we unexpectedly failed - e.g. if internal implementation of 
        // either ViewDragHelper or DrawerLayout changed
    }

Explanation:

The hack is based on the fact that DrawerLayout class relies on instances of ViewDragHelper to handle the dragging. There are two instances - one for the left drawer, and one for the right one. They are getting instantiated like this:

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

    ... code omitted for brevity ..

    mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
    mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
    mLeftDragger.setMinVelocity(minVel);
    mLeftCallback.setDragger(mLeftDragger);

    mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback);
    mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
    mRightDragger.setMinVelocity(minVel);
    mRightCallback.setDragger(mRightDragger);

    ... code omitted for brevity ..
}

Both mLeftDragger and mRightDragger are private fields, and mFieldSize field in ViewDragHelper is also private. There are no public methods which would let client code to set those fields - hence the hack relies on the reflection, which is fragile towards internal implementation changes in ViewDragHelper and DrawerLayout classes.

Bonus:
A comprehensive tutorial on ViewDragHelper usage

like image 103
anikiforov Avatar answered Oct 18 '22 09:10

anikiforov