解决DrawerLayout只能从边缘滑动的问题

方法一 (利用反射)

 写个工具类

public class DrawerLeftEdgeSize {
    
    public static void setLeftEdgeSize (Activity activity, DrawerLayout drawerLayout, float displayWidthPercentage) {
        if (activity == null || drawerLayout == null) {return;}
        try {
            // 找到 ViewDragHelper 并设置 Accessible 为true
            Field leftDraggerField =
                    drawerLayout.getClass().getDeclaredField("mLeftDragger");//Right
            leftDraggerField.setAccessible(true);
            ViewDragHelper leftDragger = (ViewDragHelper) leftDraggerField.get(drawerLayout);

            // 找到 edgeSizeField 并设置 Accessible 为true
            Field edgeSizeField = leftDragger.getClass().getDeclaredField("mEdgeSize");
            edgeSizeField.setAccessible(true);
            int edgeSize = edgeSizeField.getInt(leftDragger);

            // 设置新的边缘大小
            Point displaySize = new Point();
            activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
            edgeSizeField.setInt(leftDragger, Math.max(edgeSize, (int) (displaySize.x *
                    displayWidthPercentage)));
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
    }
}

在Activity调用

DrawerLeftEdgeSize.setLeftEdgeSize(this,drawer,0.4f);

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

GestureDetector gestureDetector;

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) && Math.abs(offsetY)<=50)
                || (velocityX > 0 && velocityX > Math.abs(velocityY) && Math.abs(offsetY)<=50)) {
            return true;
        }
        return false;
    }});
@Override
public boolean dispatchTouchEvent(MotionEvent event){
    //当向右滑动的时候,拦截事件,不传下去,通过GestureDetector辅助事件的判断
    if(gestureDetector.onTouchEvent(event)){
        //打开侧边栏
        drawer.openDrawer(GravityCompat.START);
        return true;
    }
    return super.dispatchTouchEvent(event);
}

这两种方法都有各自的问题。 
第一种方法,反射修改DrawerLayout的mEdgeSize参数,在DrawerLayout中嵌入ListView时,长按ListView的item会导致侧边栏的滑出

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


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现 WindowManager 边缘左侧任意位置划出 DrawerLayout,可以按照以下步骤进行: 1. 创建一个自定义的 View,用于响应手势事件。 2. 在 onCreate() 方法中,通过 WindowManager 将该 View 添加到屏幕上,并设置 layoutParams,使其位于屏幕左侧。 3. 在该 View 的 onTouchEvent() 方法中,监听手势事件,并根据事件的滑动距离,调整 DrawerLayout 的位置。 具体代码如下: ```java public class CustomView extends View { private float mStartX, mStartY; private WindowManager mWindowManager; private WindowManager.LayoutParams mLayoutParams; private DrawerLayout mDrawerLayout; private int mScreenWidth; private int mScreenHeight; public CustomView(Context context, DrawerLayout drawerLayout) { super(context); mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mDrawerLayout = drawerLayout; DisplayMetrics metrics = new DisplayMetrics(); mWindowManager.getDefaultDisplay().getMetrics(metrics); mScreenWidth = metrics.widthPixels; mScreenHeight = metrics.heightPixels; mLayoutParams = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSLUCENT); mLayoutParams.gravity = Gravity.START | Gravity.TOP; mLayoutParams.x = 0; mLayoutParams.y = 0; mWindowManager.addView(this, mLayoutParams); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mStartX = event.getRawX(); mStartY = event.getRawY(); break; case MotionEvent.ACTION_MOVE: float dx = event.getRawX() - mStartX; float dy = event.getRawY() - mStartY; mLayoutParams.x = (int) Math.max(0, Math.min(mScreenWidth - mDrawerLayout.getWidth(), dx)); mLayoutParams.y = (int) Math.max(0, Math.min(mScreenHeight - mDrawerLayout.getHeight(), dy)); mWindowManager.updateViewLayout(this, mLayoutParams); break; case MotionEvent.ACTION_UP: if (mLayoutParams.x >= mScreenWidth - mDrawerLayout.getWidth() / 2) { mLayoutParams.x = mScreenWidth - mDrawerLayout.getWidth(); mWindowManager.updateViewLayout(this, mLayoutParams); } else { mLayoutParams.x = 0; mWindowManager.updateViewLayout(this, mLayoutParams); } break; } return true; } } ``` 在 Activity 中创建 CustomView 实例,并将其添加到 DrawerLayout 左侧即可实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值