利用LayoutParams.y设置组件跟随手指滑动时遇到的问题

今天写代码时遇到一个问题,即使用WindowManger添加了一个组件之后,通过设置OnTouchListener来给组件添加跟随手指移动的事件。代码如下:

b.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                layoutParams.x = rawX;
                layoutParams.y = rawY;
                manager.updateViewLayout(b, layoutParams);
                break;
            default:
                break;
        }
        return false;
    }
});

实际使用中很快遇到了问题,就是在我滑动组件的一刹那,组件会有一次位置的突变。

经过分析,layoutParams.x和layoutParams.y设置的是组件左上角的坐标,而getRawX、getRawY是到屏幕左上角到手指点击位置的距离,即中间多了一段event.getX和event.getY。好吧,修改后的代码如下:

b.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        int disX = rawX - downX;
        int disY = rawY - downY;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getX();
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                layoutParams.x = disX;
                //75是我手机消息栏的高度,好吧,消息栏高度的获取方法
                layoutParams.y = disY;
                manager.updateViewLayout(b, layoutParams);
                break;
            default:
                break;
        }
        return false;
    }
});

实际使用中发现,X轴不突变了,Y轴还在突变,这是因为什么?

经过分析,发现问题出现在这里:


假如我们利用layoutParams将组件高度设置为0时,可以看到此时组件是处于通知栏下的。但是触摸顶端时,组件的event.getRawY不为0,为通知栏高度。


上述代码中我们用layoutParams.y设置组件的高度时,组件在屏幕的实际高度为 y + 通知栏 高度。我们通过getRawY-getY获取移动的高度是包含了通知栏的。但是由于我们是通过layoutParams.y设置组件高度的,而layoutParams.y是不需要通知栏高度的。所以getRawY-getY的结果还要减去通知栏高度才能正确移动。


归结到底,还是因为layoutParams.y不包括通知栏高度,而getRawY是纯粹的屏幕计算,所以包括通知栏高度。


知道了原因,修改后的代码如下:

b.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        int disX = rawX - downX;
        int disY = rawY - downY;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getX();
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                layoutParams.x = disX;
                //75是我手机消息栏的高度,好吧,通知栏高度的获取方法
                layoutParams.y = disY - statusBarHeight;
                manager.updateViewLayout(b, layoutParams);
                break;
            default:
                break;
        }
        return false;
    }
});

其中获取通知栏高度的代码如下:

public static int getStatusBarHeight(Context context) {
    Class<?> c = null;
    Object obj = null;
    Field field = null;
    int x = 0, statusBarHeight = 0;
    try {
        c = Class.forName("com.android.internal.R$dimen");
        obj = c.newInstance();
        field = c.getField("status_bar_height");
        x = Integer.parseInt(field.get(obj).toString());
        statusBarHeight = context.getResources().getDimensionPixelSize(x);
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    return statusBarHeight;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值