Canvas 捏合缩放后手指绘制坐标错误

Canvas getting wrong coordinates for finger drawing after pinch to zoom

我创建了 canvas 手指绘图应用程序,例如 https://play.google.com/store/apps/details?id=jp.naver.linebrush.android 上的线刷,我完成了缩放功能,但问题是在放大和缩小之后,没有在 [= 上正确绘制位置15=] 区域。为了获得更多理解,我分享了我对 canvas 绘图的看法 class:

public class DrawingView extends View {

//  Zooming Code 16-6-2015 4.12pm

    private static final int INVALID_POINTER_ID = -1;
     public Bitmap mMyChracter;
     private float mPosX;
     private float mPosY;

     private float mLastTouchX;
     private float mLastTouchY;
     private int mActivePointerId = INVALID_POINTER_ID;

     View currentView;
     private ScaleGestureDetector mScaleDetector;
     private float mScaleFactor = 1.f;

     private float focusX;
     private float focusY;

     private float lastFocusX = -1;
     private float lastFocusY = -1;

     static final int IMG_WIDTH = 640;
     static final int IMG_HEIGHT = 480;

     static final int IMAGE_X_POS = 560;
     static final int IMAGE_Y_POS = 20;

     float sy;
     float sx;
     public static Context context;
//   -------------------------------------


//   ...................................

        /*private final Bitmap bitmap;
        private final int width;
        private final int height;*/

        private Matrix transform = new Matrix();

        private Vector2D position = new Vector2D();
        private float scale = 1;
        private float angle = 0;

        private TouchManager touchManager = new TouchManager(2);
        private boolean isInitialized = false;

        // Debug helpers to draw lines between the two touch points
        private Vector2D vca = null;
        private Vector2D vcb = null;
        private Vector2D vpa = null;
        private Vector2D vpb = null;
        int mWidth;
        int mHeight;
//      ...............................

    private final Paint mDefaultPaint;

    private Paint mFillPaint;
    float x, y;
    private Canvas mLayerCanvas = new Canvas();
    private Bitmap mLayerBitmap;

    private Stack<DrawOp> mDrawOps = new Stack<>();
    private Stack<DrawOp> mUndoOps = new Stack<>();

    private SparseArray<DrawOp> mCurrentOps = new SparseArray<>(0);


//  For Drag and Pan zoom Code initialization
    private static float MIN_ZOOM = 1f;

    private static float MAX_ZOOM = 2f;
    private float scaleFactor = 1.f;

    private static ScaleGestureDetector detector; 

    boolean mFlagDrawing;

    private final Matrix mMatrix = new Matrix();

     int y_old=0,y_new=0;int zoomMode=0;
     float pinch_dist_old=0,pinch_dist_new=0;
     int zoomControllerScale=1;//new and old pinch distance to determine Zoom scale
        // These matrices will be used to move and zoom image
        Matrix matrix = new Matrix();
        Matrix savedMatrix = new Matrix();

        // Remember some things for zooming
        PointF start = new PointF();
        PointF mid = new PointF();
        float oldDist = 1f;

        // We can be in one of these 3 states
        static final int NONE = 0;
        static final int PAN = 1;
        static final int ZOOM = 2;
        int mode = NONE;

     private static final String TAG = "DebugTag";



//     New Code
     private Bitmap imgBitmap = null;

     private int containerWidth;
     private int containerHeight;

     Paint background;   

     //Matrices will be used to move and zoom image
//     Matrix matrix = new Matrix();
//     Matrix savedMatrix = new Matrix();

//     PointF start = new PointF();       

     float currentScale;
     float curX;
     float curY;

     //We can be in one of these 3 states
//     static final int NONE = 0;
//     static final int DRAG = 1;
//     static final int ZOOM = 2;
//     int mode = NONE;

     //For animating stuff   
     float targetX;
     float targetY;
     float targetScale;
     float targetScaleX;
     float targetScaleY;
     float scaleChange;
     float targetRatio;
     float transitionalRatio;

     float easing = 0.2f;   
     boolean isAnimating = false;

     float scaleDampingFactor = 0.5f;

     //For pinch and zoom
//     float oldDist = 1f;   
//     PointF mid = new PointF();

     private Handler mHandler = new Handler();       

     float minScale;
     float maxScale = 8.0f;

     float wpRadius = 25.0f;
     float wpInnerRadius = 20.0f;

     float screenDensity;

     private GestureDetector gestureDetector;

     public static final int DEFAULT_SCALE_FIT_INSIDE = 0;
     public static final int DEFAULT_SCALE_ORIGINAL = 1;

     private int defaultScale;


     private static final String EXTRA_EVENT_LIST = "event_list";
     private static final String EXTRA_STATE = "instance_state";
     private ArrayList<MotionEvent> eventList = new ArrayList<MotionEvent>(100);

    public DrawingView(Context context) {
        this(context, null, 0);
    }

    public DrawingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
//      detector = new ScaleGestureDetector(getContext(), new ScaleListener());
    }

    public DrawingView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mDefaultPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mDefaultPaint.setStyle(Paint.Style.STROKE);
        mDefaultPaint.setStrokeJoin(Paint.Join.ROUND);
        mDefaultPaint.setStrokeCap(Paint.Cap.ROUND);
        mDefaultPaint.setStrokeWidth(40);
        mDefaultPaint.setColor(Color.GREEN);

        /*mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mFillPaint.setStyle(Paint.Style.STROKE);
        mFillPaint.setStrokeJoin(Paint.Join.ROUND);
        mFillPaint.setStrokeCap(Paint.Cap.ROUND);
        mDefaultPaint.setStrokeWidth(40);
        mFillPaint.setColor(Color.GREEN);*/

        setFocusable(true);
        setFocusableInTouchMode(true);
        setBackgroundColor(Color.WHITE);

        setLayerType(LAYER_TYPE_SOFTWARE, null);
        setSaveEnabled(true);

//      Code for Zoom start
//      detector = new ScaleGestureDetector(getContext(), new ScaleListener());
//      Code for Zoom finish

        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
    }


    private static float getDegreesFromRadians(float angle) {
        return (float)(angle * 180.0 / Math.PI);
    }


    // Single Touch Code
    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {

        vca = null;
        vcb = null;
        vpa = null;
        vpb = null;

        final int pointerCount = MotionEventCompat.getPointerCount(event);

        switch (MotionEventCompat.getActionMasked(event)) {
        // switch(event.getAction()){
        // switch (event.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN:
        // case MotionEventCompat.ACTION_POINTER_DOWN:
        {
            if (mFlagDrawing == true) {

        /*      final float xx = event.getX() / mScaleFactor;
                   final float yy = event.getY() / mScaleFactor;
                   mLastTouchX = xx;
                   mLastTouchY = yy;
                   mActivePointerId = event.getPointerId(0);*/

                try {
                    touchManager.update(event);

                    if (touchManager.getPressCount() == 1) {
                        vca = touchManager.getPoint(0);
                        vpa = touchManager.getPreviousPoint(0);
                        position.add(touchManager.moveDelta(0));
                    }
                    else {
                        if (touchManager.getPressCount() == 2) {
                            vca = touchManager.getPoint(0);
                            vpa = touchManager.getPreviousPoint(0);
                            vcb = touchManager.getPoint(1);
                            vpb = touchManager.getPreviousPoint(1);

                            Vector2D current = touchManager.getVector(0, 1);
                            Vector2D previous = touchManager.getPreviousVector(0, 1);
                            float currentDistance = current.getLength();
                            float previousDistance = previous.getLength();

                            if (previousDistance != 0) {
                                scale *= currentDistance / previousDistance;
                            }

                            angle -= Vector2D.getSignedAngleBetween(current, previous);
                        }
                    }

                    invalidate();
                }
                catch(Throwable t) {
                    // So lazy...
                }

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
//              mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
            } else if (mFlagDrawing == false) {
                System.out.println("mFlagDrawing: " + mFlagDrawing);
                for (int p = 0; p < pointerCount; p++) {
                    final int id = MotionEventCompat.getPointerId(event, p);
                    DrawOp current = new DrawOp(mDefaultPaint);
                    current.getPath().moveTo(event.getX(), event.getY());
                    mCurrentOps.put(id, current);
                }
            }
            // mFlagZoom = true;
            // }
        }
            break;

        case MotionEvent.ACTION_MOVE: {

            // for(int p = 0; p < pointerCount; p++){

            if (mFlagDrawing == true) {

    /*             final int pointerIndex = event.findPointerIndex(mActivePointerId);
                   final float xx = event.getX(pointerIndex) / mScaleFactor;
                   final float yy = event.getY(pointerIndex) / mScaleFactor;

                   // Only move if the ScaleGestureDetector isn't processing a gesture.
                   if (!mScaleDetector.isInProgress()) {

                    final float dx = xx - mLastTouchX;
                    final float dy = yy - mLastTouchY;
                    mPosX += dx;
                    mPosY += dy;

                    invalidate();
                   }

                   mLastTouchX = xx;
                   mLastTouchY = yy;*/

                try {
                    touchManager.update(event);

                    if (touchManager.getPressCount() == 1) {
                        vca = touchManager.getPoint(0);
                        vpa = touchManager.getPreviousPoint(0);
                        position.add(touchManager.moveDelta(0));
//                      current.add(touchManager.moveDelta(0));
                    }
                    else {
                        if (touchManager.getPressCount() == 2) {
                            vca = touchManager.getPoint(0);
                            vpa = touchManager.getPreviousPoint(0);
                            vcb = touchManager.getPoint(1);
                            vpb = touchManager.getPreviousPoint(1);

                            Vector2D current = touchManager.getVector(0, 1);
                            Vector2D previous = touchManager.getPreviousVector(0, 1);
                            float currentDistance = current.getLength();
                            float previousDistance = previous.getLength();

                            if (previousDistance != 0) {
                                scale *= currentDistance / previousDistance;
                            }
                            angle -= Vector2D.getSignedAngleBetween(current, previous);
                        }
                    }

                    invalidate();
                }
                catch(Throwable t) {
                    // So lazy...
                }

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
//              mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
            } else if (mFlagDrawing == false) {

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                final int id = MotionEventCompat.getPointerId(event, 0);

                DrawOp current = mCurrentOps.get(id);

                final int historySize = event.getHistorySize();
                for (int h = 0; h < historySize; h++) {
                    x = event.getHistoricalX(h);
                    y = event.getHistoricalY(h);
                    current.getPath().lineTo(x, y);
                }
                x = MotionEventCompat.getX(event, 0);
                y = MotionEventCompat.getY(event, 0);
                current.getPath().lineTo(x, y);

//              position.add(current.getPath());
                // }
            }
        }
            break;

        case MotionEvent.ACTION_UP:
            // case MotionEventCompat.ACTION_POINTER_UP:
            // {
            if (mFlagDrawing == true) {

//               mActivePointerId = INVALID_POINTER_ID;

                try {
                    touchManager.update(event);

                    if (touchManager.getPressCount() == 1) {
                        vca = touchManager.getPoint(0);
                        vpa = touchManager.getPreviousPoint(0);
                        position.add(touchManager.moveDelta(0));
                    }
                    else {
                        if (touchManager.getPressCount() == 2) {
                            vca = touchManager.getPoint(0);
                            vpa = touchManager.getPreviousPoint(0);
                            vcb = touchManager.getPoint(1);
                            vpb = touchManager.getPreviousPoint(1);

                            Vector2D current = touchManager.getVector(0, 1);
                            Vector2D previous = touchManager.getPreviousVector(0, 1);
                            float currentDistance = current.getLength();
                            float previousDistance = previous.getLength();

                            if (previousDistance != 0) {
                                scale *= currentDistance / previousDistance;
                            }

                            angle -= Vector2D.getSignedAngleBetween(current, previous);
                        }
                    }

                    invalidate();
                }
                catch(Throwable t) {
                    // So lazy...
                }

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
//              mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
            } else if (mFlagDrawing == false) {
                System.out.println("mFlagDrawing: " + mFlagDrawing);
                for (int p = 0; p < pointerCount; p++) {
                    final int id = MotionEventCompat.getPointerId(event, p);
                    mDrawOps.push(mCurrentOps.get(id));
                    mCurrentOps.remove(id);
                    // }
                    updateLayer();
                }
            }
            // }
            break;

        case MotionEvent.ACTION_CANCEL: {

            if (mFlagDrawing == true) {

//               mActivePointerId = INVALID_POINTER_ID;

                try {
                    touchManager.update(event);

                    if (touchManager.getPressCount() == 1) {
                        vca = touchManager.getPoint(0);
                        vpa = touchManager.getPreviousPoint(0);
                        position.add(touchManager.moveDelta(0));
                    }
                    else {
                        if (touchManager.getPressCount() == 2) {
                            vca = touchManager.getPoint(0);
                            vpa = touchManager.getPreviousPoint(0);
                            vcb = touchManager.getPoint(1);
                            vpb = touchManager.getPreviousPoint(1);

                            Vector2D current = touchManager.getVector(0, 1);
                            Vector2D previous = touchManager.getPreviousVector(0, 1);
                            float currentDistance = current.getLength();
                            float previousDistance = previous.getLength();

                            if (previousDistance != 0) {
                                scale *= currentDistance / previousDistance;
                            }

                            angle -= Vector2D.getSignedAngleBetween(current, previous);
                        }
                    }

                    invalidate();
                }
                catch(Throwable t) {
                    // So lazy...
                }

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
//              mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
            } else if (mFlagDrawing == false) {
                System.out.println("mFlagDrawing: " + mFlagDrawing);
                for (int p = 0; p < pointerCount; p++) {
                    mCurrentOps
                            .remove(MotionEventCompat.getPointerId(event, p));
                }
            }
            // mFlagZoom = true;
            // }
        }
            break;

        /*case MotionEvent.ACTION_POINTER_UP: {   

               final int pointerIndex = (event.getAction() &    MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
               final int pointerId = event.getPointerId(pointerIndex);
               if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = event.getX(newPointerIndex) / mScaleFactor;
                mLastTouchY = event.getY(newPointerIndex) / mScaleFactor;
                mActivePointerId = event.getPointerId(newPointerIndex);
               }
               break;
              }*/
        default:
            return false;
        }

        invalidate();

        return true;
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldW, int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        /*mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mLayerCanvas.setBitmap(mLayerBitmap);*/

        if(mLayerBitmap == null){
             mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            }else{
                Bitmap temporary = Bitmap.createScaledBitmap(mLayerBitmap, w, h, true);
                mLayerBitmap = temporary;
            }
         mLayerCanvas = new Canvas(mLayerBitmap);

//       mLayerCanvas.rotate(90);
        /* matrix.setTranslate(1.5f,1.5f);
         matrix.postRotate(90, 2.5f, 2.5f);*/

//       updateLayer();


 /*       //Reset the width and height. Will draw bitmap and change
        containerWidth = w;
        containerHeight = h;

        if(mLayerBitmap != null) {
            int imgHeight = mLayerBitmap.getHeight();
            int imgWidth = mLayerBitmap.getWidth();

            float scale;
            int initX = 0;
            int initY = 0;           

            if(defaultScale == DrawingView.DEFAULT_SCALE_FIT_INSIDE) {               
                if(imgWidth > containerWidth) {           
                    scale = (float)containerWidth / imgWidth;           
                    float newHeight = imgHeight * scale;           
                    initY = (containerHeight - (int)newHeight)/2;

                    matrix.setScale(scale, scale);
                    matrix.postTranslate(0, initY);
                }
                else {           
                    scale = (float)containerHeight / imgHeight;
                    float newWidth = imgWidth * scale;
                    initX = (containerWidth - (int)newWidth)/2;

                    matrix.setScale(scale, scale);
                    matrix.postTranslate(initX, 0);
                }

                curX = initX;
                curY = initY;

                currentScale = scale;
                minScale = scale;
            }
            else {
                if(imgWidth > containerWidth) {                                   
                    initY = (containerHeight - (int)imgHeight)/2;                   
                    matrix.postTranslate(0, initY);
                }
                else {                               
                    initX = (containerWidth - (int)imgWidth)/2;                   
                    matrix.postTranslate(initX, 0);
                }

                curX = initX;
                curY = initY;

                currentScale = 1.0f;
                minScale = 1.0f;               
            }


            invalidate();           
        }*/

    }

    private void updateLayer() {
        mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        for (DrawOp drawOp : mDrawOps) {
            if (drawOp != null) {
                drawOp.draw(mLayerCanvas);
            }
        }
        invalidate();
    }

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

        if (isInEditMode()) {
            return;
        }

//      if(mFlagDrawing == true){
        if (!isInitialized) {
            int w = getWidth();
            int h = getHeight();
            position.set(w / 2, h / 2);
            isInitialized = true;
        }

        mWidth = mLayerBitmap.getWidth();
        mHeight = mLayerBitmap.getHeight();
//      Code for Zoom start
/*      canvas.save();
        canvas.scale(mScaleFactor, mScaleFactor, focusX, focusY);
        canvas.translate(mPosX, mPosY);*/
//      canvas.scale(scaleFactor, scaleFactor);

        /*canvas.scale(mScaleFactor, mScaleFactor, super.getWidth() * 0.5f,
                    super.getHeight() * 0.5f);*/

//      Code for Zoom finish
//      canvas.save();
        transform.reset();
        transform.postTranslate(-mWidth / 2.0f, -mHeight / 2.0f);
//      transform.postRotate(getDegreesFromRadians(angle));
        transform.postScale(scale, scale);
        transform.postTranslate(position.getX(), position.getY());
        canvas.drawBitmap(mLayerBitmap, transform, null);
//      }
//      else if(mFlagDrawing == false){
//      canvas.drawBitmap(mLayerBitmap, 0, 0, null);
        for (int i = 0; i < mCurrentOps.size(); i++) {
            DrawOp current = mCurrentOps.valueAt(i);
            if (current != null) {
                current.draw(canvas);
            }
        }
//      }
//      Code for Zoom
//      canvas.restore();

    }

    public void operationClear() {
        mDrawOps.clear();
        mUndoOps.clear();
        mCurrentOps.clear();
        updateLayer();
    }

    public void operationUndo() {
        if (mDrawOps.size() > 0) {
            mUndoOps.push(mDrawOps.pop());
            updateLayer();
        }
    }

    public void operationRedo() {
        if (mUndoOps.size() > 0) {
            mDrawOps.push(mUndoOps.pop());
            updateLayer();
        }
    }

    public void setPaintStrokeWidth(float widthPx) {
        mDefaultPaint.setStrokeWidth(widthPx);
    }

    public void setPaintOpacity(int percent) {
        int alphaValue = (int) Math.round(percent * (255.0 / 100.0));
        mDefaultPaint.setColor(combineAlpha(mDefaultPaint.getColor(),
                alphaValue));
    }

    public void setPaintColor(String color) {
        mDefaultPaint.setColor(combineAlpha(Color.parseColor(color), mDefaultPaint.getAlpha()));
    }

    public void setPaintColor(int color) {
        mDefaultPaint.setColor(combineAlpha(color, mDefaultPaint.getAlpha()));
    }

    public void setPaintMaskFilter(MaskFilter filter) {
        mDefaultPaint.setMaskFilter(filter);
    }

    public void setPaintShader(BitmapShader shader) {
        mDefaultPaint.setShader(shader);
    }

    public void setPaintColorFilter(ColorFilter colorFilter) {
        mDefaultPaint.setColorFilter(colorFilter);
    }

    private static int combineAlpha(int color, int alpha) {
        return (color & 0x00FFFFFF) | ((alpha & 0xFF) << 24);
    }

    private static class DrawOp {
        private float x,y;
        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private final Path mPath = new Path();

        public DrawOp(Paint paint) {
            reset(paint);
        }

        /*public void add(Vector2D moveDelta) {
            // TODO Auto-generated method stub
            this.x += moveDelta.getX();
            this.y += moveDelta.getY();

        }*/

        void reset(Paint paint) {
            mPath.reset();
            update(paint);
        }

        void update(Paint paint) {
            mPaint.set(paint);
        }

        void draw(Canvas canvas) {
            canvas.drawPath(mPath, mPaint);
        }

        public Path getPath() {
            return mPath;
        }

    /*  public DrawOp add(DrawOp value) {
            this.x += value.getX();
            this.y += value.getY();
            return this;
        }*/

        /*public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }*/

    }
    public void fillShapeColor(){



    }


//  Code for Zoom
/*  private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        @Override

        public boolean onScale(ScaleGestureDetector detector) {

        scaleFactor *= detector.getScaleFactor();

        scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));

        invalidate();

        return true;

        }

        }*/

     private class ScaleListener extends
       ScaleGestureDetector.SimpleOnScaleGestureListener {
      @Override
      public boolean onScaleBegin(ScaleGestureDetector detector) {

       // float x = detector.getFocusX();
       // float y = detector.getFocusY();

       lastFocusX = -1;
       lastFocusY = -1;

       return true;
      }

      @Override
      public boolean onScale(ScaleGestureDetector detector) {
       mScaleFactor *= detector.getScaleFactor();

       focusX = detector.getFocusX();
       focusY = detector.getFocusY();


       if (lastFocusX == -1)
        lastFocusX = focusX;
       if (lastFocusY == -1)
        lastFocusY = focusY;

       mPosX += (focusX - lastFocusX);
       mPosY += (focusY - lastFocusY);
       Log.v("Hi Zoom", "Factor:"  + mScaleFactor);
       // Don't let the object get too small or too large.
       mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 2.0f));

       lastFocusX = focusX;
       lastFocusY = focusY;

       invalidate();
       return true;
      }
     }


/*    @Override
    public Parcelable onSaveInstanceState() 
    {
        System.out.println("save instance");
        Bundle bundle = new Bundle();
        bundle.putParcelable(EXTRA_STATE, super.onSaveInstanceState());  
        bundle.putParcelableArrayList(EXTRA_EVENT_LIST, eventList);

    return bundle;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) 
    {
        if (state instanceof Bundle) 
        {
            Bundle bundle = (Bundle) state;
            super.onRestoreInstanceState(bundle.getParcelable(EXTRA_STATE));
            eventList = bundle.getParcelableArrayList(EXTRA_EVENT_LIST);
            if (eventList == null) {
               eventList = new ArrayList<MotionEvent>(100); 
            }
            for (MotionEvent event : eventList) {
//               performTouchEvent(event);
            }               
            return;
        }
        super.onRestoreInstanceState(state);
    }*/

    public void setDrawingFlag(boolean flag) {
//      System.out.println("Before Set mFlag " + mFlagDrawing);
        this.mFlagDrawing = flag;
//      System.out.println("After Set mFlag " + mFlagDrawing);
    }


    public void moveCanvas(float x, float y) {
        float dx = x - mLastTouchX;
        float dy = y - mLastTouchY;
        // Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
        // at 200% zoom causes the image to slide 20 pixels instead of perfectly
        // following the user's touch
        dx /= (mScaleFactor * 2);
        dy /= (mScaleFactor * 2);

        mPosX += dx;
        mPosY += dy;

        // Log.v(TAG, "moving by " + dx + "," + dy + " mScaleFactor: " +
        // mScaleFactor);
    }
}

我发现错误并自行更正。下面是我的代码。

public void resetZoom() {
        mPanX = mPanY = 0;
        final Matrix m = new Matrix();
        m.postScale(1f / DENSITY, 1f / DENSITY);
        setZoom(m);
        invalidate();
    }

    public void setZoomPosNoInval(float x, float y) {
        mPanX = x;
        mPanY = y;
    }

    public void setZoomPos(float x, float y) {
        setZoomPosNoInval(x, y);
        invalidate();
    }

    public void setZoomPosNoInval(float[] pos) {
        setZoomPosNoInval(pos[0], pos[1]);
    }

    public void setZoomPos(float[] pos) {
        setZoomPosNoInval(pos);
        invalidate();
    }

    public float[] getZoomPos(float[] pos) {
        if (pos == null)
            pos = new float[2];
        pos[0] = mPanX;
        pos[1] = mPanY;
        return pos;
    }

    public float getZoomPosX() {
        return mPanX;
    }

    public float getZoomPosY() {
        return mPanY;
    }

    public Matrix getZoom() {
        return mZoomMatrix;
    }

    public Matrix getZoomInv() {
        return mZoomMatrixInv;
    }

    public void setZoom(Matrix m) {
        mZoomMatrix.set(m);
        mZoomMatrix.invert(mZoomMatrixInv);
    }