Skip to content

Instantly share code, notes, and snippets.

@dbachelder
Last active May 19, 2017 11:16
Show Gist options
  • Save dbachelder/9550766 to your computer and use it in GitHub Desktop.
Save dbachelder/9550766 to your computer and use it in GitHub Desktop.
A version of support DrawerLayout that can open the drawer X pixels... uses reflection to access the private members of DrawerLayout
// example usage
// set up in XML and in class exactly the same as a DrawerLayout... then you can do something like this..
peekableDrawerLayout.postDelayed(new Runnable() {
@Override
public void run() {
peekableDrawerLayout.openDrawerToOffset(200.0F);
peekableDrawerLayout.postDelayed(new Runnable() {
@Override
public void run() {
peekableDrawerLayout.closeDrawers();
}
}, 1000);
}
}, 2000);
package android.support.v4.widget;
import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import timber.log.Timber;
import java.lang.reflect.Field;
/**
* uses reflection to manipulate the private fields of the super class to achieve a programmatic animated drawer open to a specified offset
*/
public class PeekableDrawerLayout extends DrawerLayout {
WindowManager windowManager;
private Field mLeftDraggerField;
private Field mRightDraggerField;
ViewDragHelper mRightDragger;
ViewDragHelper mLeftDragger;
public PeekableDrawerLayout(Context context) {
super(context);
init();
}
public PeekableDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PeekableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
protected void init() {
windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
try {
mLeftDraggerField = DrawerLayout.class.getDeclaredField("mLeftDragger");
mLeftDraggerField.setAccessible(true);
mRightDraggerField = DrawerLayout.class.getDeclaredField("mRightDragger");
mRightDraggerField.setAccessible(true);
} catch (NoSuchFieldException e) {
Timber.e(e, "unfortunate and unforeseen problem manipulating ");
throw new RuntimeException(e);
}
}
public void openDrawerToOffset(float slideOffset) {
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child == null || !isDrawerView(child)) {
continue;
}
final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
final int absGravity = GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
final ViewDragHelper helper;
int finalLeft;
if (absGravity == Gravity.LEFT) {
helper = getLeftDragger();
finalLeft = (int) (slideOffset - child.getWidth());
} else {
helper = getRightDragger();
finalLeft = (int) (getDisplayWidth() - slideOffset);
}
helper.cancel();
helper.smoothSlideViewTo(child, finalLeft, child.getTop());
invalidate();
}
}
public int getDisplayWidth() {
Display display = windowManager.getDefaultDisplay();
int width;
if(Build.VERSION.SDK_INT >= 13) {
Point size = new Point();
display.getSize(size);
width = size.x;
} else {
//noinspection deprecation
width = display.getWidth();
}
return width;
}
public ViewDragHelper getLeftDragger() {
if (mLeftDragger == null) {
try {
mLeftDragger = (ViewDragHelper) this.mLeftDraggerField.get(this);
} catch (IllegalAccessException e) {
Timber.e(e, "unfortunate and unforeseen problem manipulating ");
throw new RuntimeException(e);
}
}
return mLeftDragger;
}
public ViewDragHelper getRightDragger() {
if (mRightDragger == null) {
try {
mRightDragger = (ViewDragHelper) this.mRightDraggerField.get(this);
} catch (IllegalAccessException e) {
Timber.e(e, "unfortunate and unforeseen problem manipulating ");
throw new RuntimeException(e);
}
}
return mRightDragger;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment