您的位置:首页 > 移动开发 > Android开发

Android——DrawerLayout滑动范围的设置

2016-06-16 19:53 375 查看
最近做项目的时候需要用到DrawerLayout做侧边栏,当然自己也可以通过用ViewDragHelper来实现侧边栏优点是可高度定制化,但是比较繁琐。而DrawerLayout是系统封装好的控件,用起来简单。DrawerLayout本身内部也会通过ViewDragHelper 实现的。言归正传,系统自带的DrawLayout只能实现从屏幕边缘滑出菜单,现在需求是全屏幕任何位置都能滑出。有两种方法可以实现:

方法一:.通过反射,改变DrawerLayout的一个私有属性mEdgeSize,调整滑动范围

该方法是stackfloweOver 上的,这里找不到原链接了

Field mDragger = null;
try {
mDragger = drawerLayout.getClass().getDeclaredField(
"mLeftDragger"); //mRightDragger for right obviously
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mDragger.setAccessible(true);
ViewDragHelper draggerObj = null;
try {
draggerObj = (ViewDragHelper) mDragger
.get(drawerLayout);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Field mEdgeSize = null;
try {
mEdgeSize = draggerObj.getClass().getDeclaredField(
"mEdgeSize");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mEdgeSize.setAccessible(true);
int edge = 0;
try {
edge = mEdgeSize.getInt(draggerObj);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

try {
mEdgeSize.setInt(draggerObj, edge * 7); //optimal value as for me, you may set any constant in dp
//You can set it even to the value you want like mEdgeSize.setInt(draggerObj, 150); for 150dp
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


方法二:通过拦截Activity触摸事件的分发,实现全屏滑出菜单

在Acvtivity中,重写dispatchTouchEvent事件.简单的介绍Android 触摸事件的传递,Activity->PhoneWindow->DecorView->布局文件的根目录(也就是setContentView中传递的view)

private GestureDetector gestureDetector;

@Override
public void onCreate(Bundle b){
super.onCreate(b);
setContentView(R.layout.activity_main);
gestureDetector=new GestureDetector(this,new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//判断是否是右滑
float offsetX=e2.getX()-e1.getX();
float offsetY=e2.getY()-e1.getY();
if ((offsetX > 0 && offsetX > Math.abs(offsetY)) || (velocityX > 0 && velocityX > Math.abs(velocityY))) {
return true;//返回true表示我们在dispatchTouchEvent中,就不把事件传递到子控件中了
}
return false;
}
});
}

@Override
public boolean dispatchTouchEvent(MotionEvent event){
//当向右滑动的时候,拦截事件,不传下去,通过GestureDetector辅助事件的判断
if(gestureDetector.onTouchEvent(event)){
//打开侧边栏
drawerLayout.openDrawer(GravityCompat.START);
return true;
}
return super.dispatchTouchEvent(event);
}


这两种方法都有各自的问题。

第一种方法,反射修改DrawerLayout的mEdgeSize参数,在DrawerLayout中嵌入ListView时,长按ListView的item会导致侧边栏的滑出

第二种方法,没有了菜单滑出的跟随效果,只有一整个滑动事件完成(即手松开,或者横向滑动速度大于纵向滑动速度时)菜单才会滑出,不会滑动一点菜单出现一点。

如果有更好的方法,请多多指教
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息