Android - 捏缩放触摸事件坐标

标签 android scale android-canvas pan

我正在尝试获取我正在创建的 Android 应用程序的 Canvas 坐标。在我添加代码以使用比例焦点(以下两行)之前,它工作得很好:

scalePoint.setX((int) detector.getFocusX());
scalePoint.setY((int) detector.getFocusY());

这是我的 View 类的源代码:

    package us.kniffin.Jigsaw;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

public class TestView extends View {
    private float mLastTouchX;
    private float mLastTouchY;
    private float mPosX;
    private float mPosY;

    private Rect rect;

    private float cX, cY; // circle coords


    // Scaling objects
    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;
    // The focus point for the scaling
    private float scalePointX; 
    private float scalePointY;


    public TestView(Context context) {
        super(context);

        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    }

    @Override
    protected void onDraw(Canvas canvas) {      
        super.onDraw(canvas);
        Paint p = new Paint();
        p.setColor(Color.RED);

         rect = canvas.getClipBounds();

        canvas.save();
        canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
        canvas.translate(mPosX, mPosY);
        canvas.drawCircle(cX, cY, 10, p);

        canvas.restore();

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
         // Let the ScaleGestureDetector inspect all events.
        mScaleDetector.onTouchEvent(ev);

        final int action = ev.getAction();


        switch(action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {

            final float x = ev.getX()/mScaleFactor;// screen X position
            final float y = ev.getY()/mScaleFactor;// screen Y position

            cX = x - (rect.left * mScaleFactor) - mPosX; // canvas X
            cY = y - (rect.top * mScaleFactor) - mPosY; // canvas Y

            // Remember where we started
            mLastTouchX = x;
            mLastTouchY = y;
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            final float x = ev.getX()/mScaleFactor;
            final float y = ev.getY()/mScaleFactor;
            cX = x - (rect.left * mScaleFactor) - mPosX; // canvas X
            cY = y - (rect.top * mScaleFactor) - mPosY; // canvas Y


            // Only move if the ScaleGestureDetector isn't processing a gesture.
            if (!mScaleDetector.isInProgress()) {
                final float dx = x - mLastTouchX; // change in X
                final float dy = y - mLastTouchY; // change in Y

                mPosX += dx;
                mPosY += dy;

                invalidate();
            }

            mLastTouchX = x;
            mLastTouchY = y;

            break;

        }
        case MotionEvent.ACTION_UP: {
            mLastTouchX = 0;
            mLastTouchY = 0;
            invalidate();
        }
        }
        return true;
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();
            scalePointX =  detector.getFocusX();
            scalePointY = detector.getFocusY();

            // Don't let the object get too small or too large.
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));

            invalidate();
            return true;
        }
    }


}

有什么想法可以让这个工作正常进行吗?

更新:我将代码示例替换为另一个具有相同问题但已简化为基本要素的代码示例

再次更新:缩放后出现问题。缩放前,坐标是正确的,但缩放后,坐标太偏右下方了。看起来你缩小得越多,他们得到的错误就越多。

最佳答案

哈哈!成功!这几乎花了我一整天的时间,但我通过一堆猜测和检查弄明白了。

这是我需要的代码:

case MotionEvent.ACTION_DOWN: {
            final float x = (ev.getX() - scalePointX)/mScaleFactor;
            final float y = (ev.getY() - scalePointY)/mScaleFactor;
            cX = x - mPosX + scalePointX; // canvas X
            cY = y - mPosY + scalePointY; // canvas Y
[snip]
}

还有一段类似的 ACTION_MOVE 代码

关于Android - 捏缩放触摸事件坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9779506/

相关文章:

r - 无法在 ggplot2 上绘制比例尺或指北针

悬停时的 CSS 缩放图像,透明层和顶部的文本

android - 使用自定义形状在 Canvas 上绘制位图

android - 在我现有的 Android 项目中使用库项目(在 Eclipse 中)有哪些优点和缺点?

java - 如何解决 android (java) 中的退格错误

java - 解决java.lang.NumberFormatException : Invalid double: "" without losing placeholder text

html - 图像缩放后如何修复父元素大小?

flutter - 如何获取ui.Image(dart :ui) from network image?

android - 在 Android 上从 .png 文件绘制自定义 View 的背景

android - 如何实现带有搜索框的对话框?