d'abord tout cela est une question de suivi à l'origine posée ici, Pan, Zoom and Scale a custom View for Canvas drawing in Androidposition échelle incorrect après application de zoom sur toile Android
Comme il n'y avait pas encore de réponse, je me suis finalement résolu mon problème en utilisant la android-gesture-detectors
Après avoir appliqué le geste de zoom/échelle, j'ai trouvé que les coordonnées du dessin de toile pointent toujours sur l'ancienne position (avant d'appliquer le zoom) et ne dessinent pas exactement les mêmes coordonnées tactiles. Fondamentalement, je ne peux pas obtenir les coordonnées de toile correctes après la mise à l'échelle ou en faisant glisser le canevas.
Avant le zoom,
Après un zoom sur les points de contact sont dessin sur l'emplacement précédent. Je veux dessiner sur l'emplacement tactile en cours,
Exemple de code,
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.getFocusX(), 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, h, 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, y, 0, 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() sont classes personnalisées héritées de android-gesture-detectors
Pourriez-vous donner un exemple de code? Comme je l'ai mentionné plus tôt, c'est une question de suivi, donc vous pouvez donner votre propre idée de mise à l'échelle et zoom de la toile. –