Android Canvas ScaleFocus导致跳跃位置 [英] Android Canvas ScaleFocus causing jumping position

查看:278
本文介绍了Android Canvas ScaleFocus导致跳跃位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一款游戏,该游戏将向下看向网格移动(类似于国际象棋).我希望用户能够平移和缩放地图.我一直在转换到矩阵,然后将这些更改串联到画布矩阵.虽然大多数情况下都能正常工作,但是我有一个奇怪的错误:

I am working on a game that will be looking down onto a grid moving pieces around (similar to Chess). I want the user to be able to pan and zoom the map. I have been making transformations to a matrix, and then concatenating those changes to the canvas matrix. While it's mostly working, I have a weird bug:

在初始缩放后,如果我再次按比例缩放,则屏幕会跳转(好像在其他地方滑动并立即移动到那里一样),然后平滑缩放.我已经将这种行为缩小到了scale函数的scaleFocus变量

After the initial scale, if I pinch to scale again, the screen jumps (it's as if a swiped somewhere else and it moved there instantly) and then scales smoothly. I have narrowed this behavior down to the scaleFocus variables of the scale function

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

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

If I set scaleFocusX and scaleFocusY to 0, the always use the origin as the scale focus and the jumping does not occur. However, using the origin is not practical as you scroll farther from it. Here is a summary of my code.

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.

First of all, instead of using float[] coordinates = {x, y}; you better use PointF coordinates = new PointF(x, y);, then you can get x and y with coordinates.x and coordinates.y.

您的问题是,缩放时您仍然会处理触摸事件(因此触摸会被处理两次).

Your problem is that when scaling you still handle the touch events (so touch is handled twice).

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

We need a global variable that tells whether we are scaling or not: boolean scaling = false

因此,您应该在OnTouchEvent中对其进行检查:

So, in OnTouchEvent you should check it:

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

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

Release with: if (event.getAction() == MotionEvent.ACTION_UP) { scaling = false;

onTouchEvent中所有可用于点击的代码都应用

And all of your code in onTouchEvent that works with clicks should be surrounded with

if (!scaling) { ... }

这篇关于Android Canvas ScaleFocus导致跳跃位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆