Android-Pinch缩放触摸事件坐标
我正在尝试获取我正在创建的android应用程序的画布坐标。在我添加代码以使用缩放焦点(以下两行)之前,它工作得非常好: 以下是我的视图类的源代码:Android-Pinch缩放触摸事件坐标,android,scale,android-canvas,pan,Android,Scale,Android Canvas,Pan,我正在尝试获取我正在创建的android应用程序的画布坐标。在我添加代码以使用缩放焦点(以下两行)之前,它工作得非常好: 以下是我的视图类的源代码: package us.kniffin.Jigsaw; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Canvas; import
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;
}
}
}
你知道我需要做些什么来让它工作吗
更新:我将代码示例替换为另一个具有相同问题的代码示例,但已简化为要点
再次更新:缩放后出现问题。缩放前,坐标是正确的,但缩放后,坐标离单击位置的右侧和下方太远。看起来,缩小的越多,错误就越大。无论何时使用平移、缩放、旋转(等),都会更改画布的矩阵。 通常,此矩阵用于告诉您每个(x,y)在画布上的位置。 创建画布时,矩阵为标识矩阵: (1 ) ( 1 ) ( 1) 但只要你做了这些改变,这个矩阵也会改变。
如果你想知道正确的坐标,那么在缩放/旋转之前,你应该使用canvas.save(),缩放之后使用canvas.restore()哈哈!成功!这几乎花了我一整天的时间,但我通过一大堆猜测和检查才弄明白 以下是我需要的代码:
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]
}
我最近在做一些非常类似的事情时遇到了这个问题,经过反复尝试和大量的谷歌搜索,我最终修改了这个答案(): (e是一个MotionEvent,因此最好在onTouch或onLongPress中使用此代码)
这里可以应用一些明显的优化,但我认为这样做更清楚。如果你能制作一个更小的程序来展示同样的效果,你可能更容易得到答案。祝你好运好建议。我会的。另一个建议是:你应该解释到底发生了什么,比如你得到了什么坐标(或错误),如果它们总是偏离100或总是到大/小/随机/,为什么你要缩放以及那些可能有用的东西好吧,我也更新了。有什么建议吗?好的。我正在使用“保存和还原”,但这无助于解决我的问题。我不太明白。我用错了吗?哇,我的朋友很感激你的努力。
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]
}
mClickCoords = new float[2];
//e is the motionevent that contains the screen touch we
//want to translate into a canvas coordinate
mClickCoords[0] = e.getX();
mClickCoords[1] = e.getY();
Matrix matrix = new Matrix();
matrix.set(getMatrix());
//this is where you apply any translations/scaling/rotation etc.
//Typically you want to apply the same adjustments that you apply
//in your onDraw().
matrix.preTranslate(mVirtualX, mVirtualY);
matrix.preScale(mScaleFactor, mScaleFactor, mPivotX, mPivotY);
// invert the matrix, creating the mapping from screen
//coordinates to canvas coordinates
matrix.invert(matrix);
//apply the mapping
matrix.mapPoints(mClickCoords);
//mClickCoords[0] is the canvas x coordinate and
//mClickCoords[1] is the y coordinate.