捏缩放(绘图线)Android Canvas后获取正确的坐标
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了捏缩放(绘图线)Android Canvas后获取正确的坐标相关的知识,希望对你有一定的参考价值。
我正在尝试用用户的手指(触摸)画一条线。如果没有缩放比例,则实现起来非常容易。没有缩放的绘图效果很好,这里是屏幕截图
效果很好。如你看到的。
但是如果我缩放画布,它将开始以一些边距/测量误差/公差绘制点。似乎我在计算缩放的接触点时没有预先取值,我尝试了很多不同的公式,但是没有任何帮助。
似乎我必须考虑到某些增量值中的问题
因为如果使用此版本的缩放功能,它可以很好地工作,但只能缩放到左上角。
canvas.scale(mScaleFactor, mScaleFactor);
具有此缩放比例
canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
多点触控缩放(捏)效果很好,但坐标不正确。
[请帮助解决问题,似乎在计算缩放的x和y时我必须采用这些scalePointX, scalePointY
变量。
这是我的代码。任何帮助将不胜感激。
private void initWorkSpace(Context context)
mPaint = new Paint();
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mRect = new Rect();
mPath = new Path();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(10f);
@Override
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
canvas.getClipBounds(mRect);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
canvas.translate(mRect.top,mRect.left);
canvas.drawPath(mPath, mPaint);
canvas.restore();
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y)
mPath.moveTo(x, y);
mX = x;
mY = y;
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y)
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE)
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
public void clearCanvas()
mPath.reset();
invalidate();
// when ACTION_UP stop touch
private void upTouch()
mPath.lineTo(mX, mY);
@Override
public boolean onTouchEvent(MotionEvent ev)
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
Log.e("TOUCH","REAL X :" + ev.getX() + " REAL Y : " + ev.getY());
Log.e("TOUCH","RECT TOP :" + mRect.top + " RECT LEFT : " + mRect.left + " RECT RIGHT : " + mRect.right + " RECT BOTTOM :" + mRect.bottom);
final float scaledX = ev.getX()/mScaleFactor+mRect.left*mScaleFactor;
final float scaledY = ev.getY()/mScaleFactor+mRect.top*mScaleFactor;
switch (action & MotionEvent.ACTION_MASK)
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*/
// Remember where we started
mLastTouchX = scaledX;
mLastTouchY = scaledY;
Log.e("DOWN","Scale FACTOR : " + mScaleFactor);
Log.e("DOWN","X : " +mLastTouchX + " Y :" + mLastTouchY + " scalePointX : " + scalePointX + " scalePointY : " + scalePointY );
Log.e("DOWN","Last X : " + mLastTouchY + " Last Y :" + mLastTouchY);
startTouch(mLastTouchX, mLastTouchY);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
/* 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
// 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();
*/
Log.e("ACTION_MOVE","Scale FACTOR : " + mScaleFactor);
Log.e("ACTION_MOVE","X : " + scaledX + " Y :" + scaledY + " cX : " + cX + " cY : " + cY );
Log.e("ACTION_MOVE","Last X : " + mLastTouchX + " Last Y :" + mLastTouchY);
mLastTouchX = scaledX;
mLastTouchY = scaledY;
moveTouch(scaledX, scaledY);
invalidate();
break;
case MotionEvent.ACTION_UP:
mLastTouchX = 0;
mLastTouchY = 0;
upTouch();
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));
mScaleFactor = (mScaleFactor < 1 ? 1 : mScaleFactor);
invalidate();
return true;
您只需要将屏幕坐标转换为修改后的画布坐标:请执行以下方法:
//如果您已经移动(转移)了画布:TouchX = TouchX-translatedX;TouchY = TouchY-translationY;
//如果已缩放画布:TouchX = TouchX / scaleFactor;TouchY = TouchY / scaleFactor;
//如果您已翻译画布并对其进行缩放:TouchX =(TouchX-translatedX)/ scaleFactor;TouchY =(TouchY-translatedY)/ scaleFactor;
//然后使用此TouchX和TouchY进行绘制。
我希望这会有所帮助。
以上是关于捏缩放(绘图线)Android Canvas后获取正确的坐标的主要内容,如果未能解决你的问题,请参考以下文章