Android——DrawerLayout滑动范围的设置

最近做项目的时候需要用到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会导致侧边栏的滑出

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

如果有更好的方法,请多多指教

你可能感兴趣的:(android)