Android 拖动可在画布上绘制-可行,但位置不准确

Android 拖动可在画布上绘制-可行,但位置不准确,android,canvas,android-canvas,drag,android-drawable,Android,Canvas,Android Canvas,Drag,Android Drawable,我已经编程,其中可绘制的对象(下面屏幕截图中的黄色半透明瓷砖)可以在可滚动和可缩放(使用矩阵)画布上拖动: 下面是代码处理程序: private Drawable mDragged = null; private float mPrevX; private float mPrevY; public boolean onTouchEvent(MotionEvent e) { // Convert touch coordinates to Canvas coordinates f

我已经编程,其中
可绘制的
对象(下面屏幕截图中的黄色半透明瓷砖)可以在可滚动和可缩放(使用矩阵)画布上拖动:

下面是代码处理程序:

private Drawable mDragged = null;
private float mPrevX;
private float mPrevY;

public boolean onTouchEvent(MotionEvent e) {
    // Convert touch coordinates to Canvas coordinates
    float[] point = new float[] {e.getX(), e.getY()};
    Matrix inverse = new Matrix();
    mMatrix.invert(inverse);
    inverse.mapPoints(point);
    float x = point[0];
    float y = point[1];

    switch (e.getAction()) {
    case MotionEvent.ACTION_DOWN:
        Drawable tile = hitTest(x, y);
        if (tile != null) {
            mDragged = tile;
            mPrevX = x;
            mPrevY = y;
            return true;
        }
    break;
    case MotionEvent.ACTION_MOVE:
        if (mDragged != null) {
            float dX = x - mPrevX;
            float dY = y - mPrevY;
            mPrevX = x;
            mPrevY = y;

            Rect rect = mDragged.copyBounds();
            rect.left += dX;
            rect.top += dY;
            rect.right = rect.left + mDragged.getIntrinsicWidth();
            rect.bottom = rect.top + mDragged.getIntrinsicHeight();
            mDragged.setBounds(rect);

            invalidate();
            return true;
        }
    break;
    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_CANCEL:
        if (mDragged != null) {
            mDragged = null;
            return true;
        }
    break;
    }
    // Handle Canvas scrolling and scaling here
}
它可以工作,但我有一个问题——当我触摸一块瓷砖,然后拖动它时——瓷砖会从我的手指上脱落(或者从我的鼠标指针上脱落,当使用Android emulator时)

也就是说,当被拖动时,被拖动的
Drawable
与手指(或鼠标指针-如上图所示)之间的距离增加

这不可能,因为模拟器上只有单点触摸


根本原因是什么?

这只是一种预感,但可能是由于两种因素混合在一起:

  • 您的坐标是
    float
    值,但是
    Rect
    int
    值组成,这可能会导致一些舍入问题
  • 在每个动作移动事件中,添加(可能)舍入值,并更改基线(
    mPrevX
    &
    mPrevY
    ),而不是计算从第一次开始拖动的绝对距离

  • 我会在拖动开始时存储平铺的当前位置(包括从光标位置的偏移),然后根据该点进行所有移动计算。

    +1谢谢。这个问题已通过
    rect.left+=Math.round(dX)
    解决,但我也将实施您的第二个建议。