Android Canvas ScaleFocus 导致跳跃位置

Android Canvas ScaleFocus causing jumping position

我正在开发一款游戏,该游戏将俯视网格移动棋子(类似于国际象棋)。我希望用户能够平移和缩放地图。我一直在对矩阵进行转换,然后将这些更改连接到 canvas 矩阵。虽然它大部分都在工作,但我有一个奇怪的错误:

初始缩放后,如果我再次缩放,屏幕会跳跃(好像在其他地方滑动并立即移动到那里)然后平滑缩放。我已将此行为缩小到缩放函数的 scaleFocus 变量

canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);

如果我将 scaleFocusX 和 scaleFocusY 设置为 0,则始终使用原点作为缩放焦点并且不会发生跳跃。但是,当您滚动到离原点更远的地方时,使用原点是不切实际的。这是我的代码摘要。

public void onDraw(Canvas canvas) {
  ...
  canvas.translate(-mPosX, -mPosY);
  canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);

  //Create an inverse of the tranformation matrix, to be used when determining click location.
  canvas.getMatrix().invert(canvasMatrix);
  ... }


public class MyOnScaleGestureListener extends
        ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScale(ScaleGestureDetector detector) {

        scaleFactor *= detector.getScaleFactor();
        // Don't let the object get too small or too large.
        scaleFactor = Math.max(MIN_SCALE, Math.min(scaleFactor, MAX_SCALE));
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        Point scaleFocus = calculateClickAbsoluteLocation
                (detector.getFocusX(), detector.getFocusY());
        scaleFocusX = scaleFocus.x;
        scaleFocusY = scaleFocus.y;
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {

    }


//This method will take point on the phone screen, and convert it to be
//a point on the canvas (since the canvas area is larger than the screen).
public Point calculateClickAbsoluteLocation(float x, float y) {
    Point result = new Point();
    float[] coordinates = {x, y};

    //MapPoints will essentially convert the click coordinates from "screen pixels" into
    //"canvas pixels", so you can determine what tile was clicked.
    canvasMatrix.mapPoints(coordinates);

    result.set((int)coordinates[0], (int)coordinates[1]);
    return result;
}

首先,而不是使用 float[] coordinates = {x, y}; 你最好使用 PointF coordinates = new PointF(x, y);,然后你可以用 coordinates.xcoordinates.y.

得到 xy

你的问题是当缩放时你仍然处理触摸事件(所以触摸被处理了两次)。

我们需要一个全局变量来告诉我们是否正在缩放: boolean scaling = false

所以,在 OnTouchEvent 中你应该检查它:

@Override
    public boolean onTouchEvent(@NonNull MotionEvent event) { 
        detector.onTouchEvent(event);
        if (detector.isInProgress()) 
            scaling = true;

发布: 如果 (event.getAction() == MotionEvent.ACTION_UP) { 缩放=假;

onTouchEvent 中与点击相关的所有代码都应包含在

if (!scaling) { ... }