画布 - 在Android上放大,移动和缩放

ono*_*ono 14 android android-canvas

我目前正在webview图像(下面的大象)上实现绘图功能.我没有绘制它的问题,但缩放功能在绘图上做了一些时髦的东西(下面的第2张图片).当我放大时,绘图不会缩放而是转换.缩放绘图也不起作用.我的代码如下:

正常

在此输入图像描述

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.save();
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    canvas.drawPath(drawPath, drawPaint);
    canvas.scale(mScaleFactor, mScaleFactor);
    canvas.restore();
    clipBounds = canvas.getClipBounds();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleDetector.onTouchEvent(event);
    float touchX = event.getX() / mScaleFactor + clipBounds.left;
    float touchY = event.getY() / mScaleFactor + clipBounds.top;
    if (Deal.on)
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                drawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;
            default:
                return false;
    }
    else {
        super.onTouchEvent(event);
    }
    invalidate();
    return true;
}

public class ScaleGestureListener extends 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Edit: I managed to get the canvas to redraw with zooming using the GestureDetector's scale factor. Additionally, I have a switch that toggles from drawing to zooming/webview controls. A problem that I run into is that double tap on WebView doesn't trigger the onScale gesture. Which means the canvas doesn't get redrawn and shifts on the zoom in.

I need to implement a feature that detects how much the scale factor is affected by the double tap zoom in. If anyone can suggest a solution to that. Here's the update code:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    clipBounds = canvas.getClipBounds();
    canvas.save();
    drawPaint.setStrokeWidth(8/mScaleFactor);
    canvas.scale(mScaleFactor, mScaleFactor, 0, 0);
    canvas.drawPath(drawPath, drawPaint);
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    canvas.restore();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    pointerCount = event.getPointerCount();
    mScaleDetector.onTouchEvent(event);
    float touchX = (event.getX() + clipBounds.left) / mScaleFactor;
    float touchY = (event.getY() + clipBounds.top) / mScaleFactor;
    if (Deal.on){
        if (event.getPointerCount() > 1){
            return false;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                drawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;
            default:
                return false;
        }
    }
    else {
        super.onTouchEvent(event);
    }
    invalidate();
    return true;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   // Try for a width based on our minimum
   int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
   int w = resolveSizeAndState(minw, widthMeasureSpec, 1);

   //int minh = MeasureSpec.getSize(w) - (int)mTextWidth + getPaddingBottom() + getPaddingTop();
   int h = resolveSizeAndState(MeasureSpec.getSize(w), heightMeasureSpec, 0);
   setMeasuredDimension(w, h);
}

public class ScaleGestureListener extends SimpleOnScaleGestureListener {

    @Override
    public boolean onScale(ScaleGestureDetector detector) {

        // Don't let the object get too small or too large.
        if(Deal.on == false) {
            mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(1f, Math.min(mScaleFactor, 20.0f));
        }

        invalidate();

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

Tor*_*erg 3

我已经实现了这种行为,但方式略有不同。我使用矩阵来处理所有缩放和滚动(以及旋转,在我的例子中)。它使得代码简洁并且工作起来像发条一样。不过,我不知道是什么导致了你的怪异行为。

将 Matrix 和另一个路径存储为类成员:

Matrix drawMatrix = new Matrix();
Path transformedPath = new Path();
Run Code Online (Sandbox Code Playgroud)

更换您的 onScale:

@Override
public boolean onScale(ScaleGestureDetector detector) {
    Matrix transformationMatrix = new Matrix();

    //Zoom focus is where the fingers are centered, 
    transformationMatrix.postTranslate(-detector.getFocusX(), -detector.getFocusY());

    transformationMatrix.postScale(detector.getScaleFactor(), detector.getScaleFactor());

/* Using getFocuShift allows for scrolling with two pointers down. Remove it to skip this functionality */
    transformationMatrix.postTranslate(detector.getFocusX() + detector.getFocusShiftX(), detector.getFocusY() + detector.getFocusShiftY());

    drawMatrix.postConcat(transformationMatrix);
    invalidate();
    return true;
}
Run Code Online (Sandbox Code Playgroud)

在 onDraw 中;跳过保存画布,而是:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.drawBitmap(canvasBitmap, drawMatrix, canvasPaint);
    transformedPath.rewind();
    transformedMatrix.addPath(drawPath);
    transformedPath.transform(drawMatrix, null);
    canvas.drawPath(transformedPath, drawPaint);
}
Run Code Online (Sandbox Code Playgroud)

快乐编码!