利用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;
}

你可能感兴趣的:(android,通知栏高度,组件跟随手指滑动)