android 画布放大缩小,在Android画布上应用缩放效果后,缩放比例位置错误

余铭晨
2023-12-01

首先这是一个跟随问题,原来在这里提出,Pan,Zoom and Scale a custom View for Canvas drawing in Android

应用缩放/缩放手势后,我发现画布绘图坐标仍然指向旧位置(在应用缩放之前),而不是绘制完全相同的触摸坐标.基本上,在缩放或拖动画布后,无法获得正确的画布坐标.

放大前,

缩小之后,触摸点正在绘制上一个位置.我想让它画在当前的触摸位置,

示例代码,

public class DrawingView extends View {

private void setupDrawing() {

mScaleDetector = new ScaleGestureDetector(getContext(),new ScaleListener());

mgd = new MoveGestureDetector(ctx,mgl);

sgd = new ScaleGestureDetector(ctx,sgl);

rgd = new RotateGestureDetector(ctx,rgl);

}

class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

@Override

public boolean onScale(ScaleGestureDetector detector) {

mScaleFactor *= detector.getScaleFactor();

// Don't let the object get too small or too large.

mScaleFactor = Math.max(0.1f,Math.min(mScaleFactor,5.0f));

invalidate();

return true;

}

}

MoveGestureDetector.SimpleOnMoveGestureListener mgl = new MoveGestureDetector.SimpleOnMoveGestureListener() {

@Override

public boolean onMove(MoveGestureDetector detector) {

PointF delta = detector.getFocusDelta();

matrix.postTranslate(delta.x,delta.y);

invalidate();

return true;

}

};

ScaleGestureDetector.SimpleOnScaleGestureListener sgl = new ScaleGestureDetector.SimpleOnScaleGestureListener() {

@Override

public boolean onScale(ScaleGestureDetector detector) {

float scale = detector.getScaleFactor();

matrix.postScale(scale,scale,detector.getFocusX(),detector.getFocusY());

invalidate();

return true;

}

};

RotateGestureDetector.SimpleOnRotateGestureListener rgl = new RotateGestureDetector.SimpleOnRotateGestureListener() {

@Override

public boolean onRotate(RotateGestureDetector detector) {

matrix.postRotate(-detector.getRotationDegreesDelta(),detector.getFocusY());

invalidate();

return true;

}

};

@Override

protected void onSizeChanged(int w,int h,int oldw,int oldh) {

//view given size

super.onSizeChanged(w,h,oldw,oldh);

canvasBitmap = Bitmap.createBitmap(w,Bitmap.Config.ARGB_8888);

drawCanvas = new Canvas(canvasBitmap);

}

private void touch_start(float x,float y) {

undonePaths.clear();

drawPath.reset();

drawPath.moveTo(x,y);

mX = x;

mY = y;

}

private void touch_move(float x,float y,float x2,float y2) {

float dx = Math.abs(x - mX);

float dy = Math.abs(y - mY);

if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {

/* QUad to curves using a quadratic line (basically an ellipse of some sort).

LineTo is a straight line. QuadTo will smooth out jaggedies where they turn.

*/

drawPath.quadTo(mX,mY,(x + mX) / 2,(y + mY) / 2);

mX = x;

mY = y;

}

}

private void touch_up() {

drawPath.lineTo(mX,mY);

// commit the path to our offscreen

drawCanvas.drawPath(drawPath,drawPaint);

// kill this so we don't double draw

paths.add(drawPath);

drawPath = new Path();

drawPath.reset();

invalidate();

}

@Override

public boolean onTouchEvent(MotionEvent event) {

if (isZoomable) {

mgd.onTouchEvent(event);

sgd.onTouchEvent(event);

rgd.onTouchEvent(event);

}

if (!isTouchable) {

return super.onTouchEvent(event);

} else {

//detect user touch

float x = event.getX();

float y = event.getY();

switch (event.getAction() & MotionEvent.ACTION_MASK) {

case MotionEvent.ACTION_DOWN:

if (!isZoomable) {

touch_start(x,y);

}

invalidate();

break;

case MotionEvent.ACTION_MOVE:

if (!isZoomable) {

//mPositions.add(new Vector2(x - mBitmapBrushDimensions.x / 2,y - mBitmapBrushDimensions.y / 2));

if (isCustomBrush && mBitmapBrushDimensions != null) {

mPositions = new Vector2(x - mBitmapBrushDimensions.x / 2,y - mBitmapBrushDimensions.y / 2);

touch_move(x,y,x - mBitmapBrushDimensions.x / 2,y - mBitmapBrushDimensions.y / 2);

} else {

touch_move(x,0);

}

}

invalidate();

break;

case MotionEvent.ACTION_UP:

if (!isZoomable) {

touch_up();

}

invalidate();

break;

}

mScaleDetector.onTouchEvent(event);

return true;

}

}

@Override

protected void onDraw(Canvas canvas) {

canvas.save();

canvas.setMatrix(matrix);

for (Path p : paths) {

canvas.drawPath(p,drawPaint);

drawPaint.setColor(selectedColor);

drawPaint.setStrokeWidth(brushSize);

canvas.drawPath(drawPath,drawPaint);

}

canvas.restore();

}

}

PS:MoveGestureDetector(),ScaleGestureDetector()& RotateGestureDetector()是从android-gesture-detectors继承的自定义类

 类似资料: