如何通过手指在画布上画后捏放大坐标机器人改变

如何通过手指在画布上画后捏放大坐标机器人改变

本文介绍了如何通过手指在画布上画后捏放大坐标机器人改变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何机构可以有关于如何绘制使用手指缩放后的画布和缩小解决方案?我做捏放大为画布,但stucking点不是画右侧坐标。从谷歌D组;我做更多的R&放大器。我有CustomView类,下面我分享。

 公共类DrawingView扩展视图{    ArrayList的<路径和GT; pathList =新的ArrayList<路径>();    矩形mRect =新的矩形();
    私有静态最终诠释INVALID_POINTER_ID = -1;
     公共位图mMyChracter;
     私人浮动mPosX;
     私人浮动mPosY;     私人浮动mLastTouchX;
     私人浮动mLastTouchY;
     私人INT mActivePointerId = INVALID_POINTER_ID;     查看currentView;
     私人ScaleGestureDetector mScaleDetector;
     私人浮动mScaleFactor = 1.F;     私人浮动focusX;
     私人浮动focusY;     私人浮动lastFocusX = -1;
     私人浮动lastFocusY = -1;     静态最终诠释IMG_WIDTH = 640;
     静态最终诠释IMG_HEIGHT = 480;     静态最终诠释IMAGE_X_POS = 560;
     静态最终诠释IMAGE_Y_POS = 20;     布尔mFalgPath = FALSE;     布尔mFlagDrawAgain;     浮动SY;
     浮SX;
     公共静态上下文的背景下;
     路径path =新路径();
     mypath中P1 =新mypath中();
     mypath中P2 =新mypath中();     路径mNewPath =新路径();
// -------------------------------------
// ...................................        / *私人最终位图位图;
        私人最终诠释宽度;
        私人最终诠释高度; * /        私人矩阵变换=新的Matrix();        私人的Vector2D位置=新的Vector2D();
        私人浮动规模= 1;
        私人浮动角= 0;        私人TouchManager touchManager =新TouchManager(2);
        私人布尔将IsInitialized = FALSE;        //调试助手绘制两个触摸点之间的线
        私人的Vector2D VCA = NULL;
        私人的Vector2D VCB = NULL;
        私人的Vector2D VPA = NULL;
        私人的Vector2D VPB = NULL;
        INT mWidth;
        INT mHeight;
// ...............................    私人最终涂料mDefaultPaint;    私人涂料mFillPaint;
    浮动的x,y;
    私人帆布mLayerCanvas =新的Canvas();
    私人位图mLayerBitmap;    私人堆叠式和LT; D​​rawOp> mDrawOps =新的堆栈<>();
    私人堆叠式和LT; D​​rawOp> mUndoOps =新的堆栈<>();    私人SparseArray< D​​rawOp> mCurrentOps =新SparseArray&所述;>(0);
//为拖动和缩放平移code初始化
    私有静态浮动MIN_ZOOM = 1F;    私有静态浮动MAX_ZOOM = 2F;
    私人浮动比例因子= 1.F;    私有静态ScaleGestureDetector检测器;    布尔mFlagDrawing;    私人最终矩阵mMatrix =新的Matrix();     INT y_old = 0,y_new = 0; INT zoomMode = 0;
     浮pinch_dist_old = 0,pinch_dist_new = 0;
     INT zoomControllerScale = 1; //新老掐距离来确定变焦倍数
        //这些矩阵将用于移动和放大图像
        字模=新的Matrix();
        矩阵savedMatrix =新的Matrix();        //记住一些东西放大
        的PointF开始=新的PointF();
        的PointF中旬=新的PointF();
        浮oldDist = 1F;        //我们可以在这3个国家之一
        静态最终诠释NONE = 0;
        静态最终诠释潘= 1;
        静态最终诠释ZOOM = 2;
        INT模式=无;     私有静态最后弦乐TAG =DebugTag;//新的code
     私人位图imgBitmap = NULL;     私人诠释containerWidth;
     私人诠释containerHeight;     油漆背景;     //矩阵将用于移动和放大图像
//矩阵的矩阵=新的Matrix();
//矩阵savedMatrix =新的Matrix();//开始的PointF =新的PointF();     浮currentScale;
     浮curX;
     浮CURY;     //我们可以在这3个国家之一
//静态最终诠释NONE = 0;
//静态最终诠释DRAG = 1;
//静态最终诠释ZOOM = 2;
// INT模式=无;     //对于动画的东西
     浮targetX;
     浮targetY;
     浮targetScale;
     浮targetScaleX;
     浮targetScaleY;
     浮scaleChange;
     浮targetRatio;
     浮transitionalRatio;     浮宽松= 0.2F;
     布尔isAnimating = FALSE;     浮scaleDampingFactor = 0.5F;     //对于捏和缩放
//浮动oldDist = 1F;
//的PointF中旬=新的PointF();     私人处理程序mHandler =新的处理程序();     浮minScale;
     浮maxScale = 8.0f;     浮wpRadius = 25.0f;
     浮wpInnerRadius = 20.0f;     浮screenDensity;     私人GestureDetector gestureDetector;     公共静态最终诠释DEFAULT_SCALE_FIT_INSIDE = 0;
     公共静态最终诠释DEFAULT_SCALE_ORIGINAL = 1;     私人诠释defaultScale;
     私有静态最后弦乐EXTRA_EVENT_LIST =EVENT_LIST;
     私有静态最后弦乐EXTRA_STATE =instance_state;
     私人的ArrayList< MotionEvent> EVENTLIST =新的ArrayList< MotionEvent>(100);    公共DrawingView(上下文的背景下){
        这(背景下,NULL,0);
    }    公共DrawingView(上下文的背景下,ATTRS的AttributeSet){
        这(背景下,ATTRS,0);
//探测器=新ScaleGestureDetector(的getContext(),新ScaleListener());
    }    公共DrawingView(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
        超(背景下,ATTRS,defStyle);        mDefaultPaint =新的油漆(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 =新的油漆(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(真);
        setFocusableInTouchMode(真);
        setBackgroundColor(Color.WHITE);        setLayerType(LAYER_TYPE_SOFTWARE,NULL);
        setSaveEnabled(真);// code代表开始放大
//探测器=新ScaleGestureDetector(的getContext(),新ScaleListener());
// code的放大光洁度        mScaleDetector =新ScaleGestureDetector(上下文,新ScaleListener());
    }
    私有静态浮动getDegreesFromRadians(浮点角){
        回报(浮)(角度* 180.0 / Math.PI);
    }
    //单点触控code
    @覆盖
    公共布尔onTouchEvent(@NonNull MotionEvent事件){
        / *浮动J = event.getX()/ mScaleFactor + mRect.left;
         浮K = event.getY()/ mScaleFactor + mRect.top; * /        最终诠释pointerCount = MotionEventCompat.getPointerCount(事件);        开关(MotionEventCompat.getActionMasked(事件)){
        //开关(event.getAction()){
        //开关(event.getAction()及MotionEvent.ACTION_MASK){        案例MotionEvent.ACTION_DOWN:
        //情况MotionEventCompat.ACTION_POINTER_DOWN:
        {
            如果(mFlagDrawing ==真){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度    / *浮动DX = event.getX();
                浮DY = event.getY();                如果(mScaleFactor == 1.F){
                    DX = event.getX() - mPosX;
                    DY = event.getY() - mPosY;
                }
// TEMPPATH =新路径();
                DrawOp电流=新DrawOp(mDefaultPaint);
                。current.getPath()的moveTo(DX,DY); * /            }否则如果(mFlagDrawing == FALSE){
                DrawOp currentNew =新DrawOp(mDefaultPaint);                如果(mFlagDrawAgain ==真){
                    p1.moveTo(event.getX(),event.getY());
                / * path.moveTo(event.getX(),event.getY());
                    mNewPath.addPath(路径); * /
                }
                其他{
                的System.out.println(mFlagDrawing:+ mFlagDrawing);                为(中间体p值= 0; P&下; pointerCount,P ++){
                    最终诠释ID = MotionEventCompat.getPointerId(事件,P);
                    DrawOp电流=新DrawOp(mDefaultPaint);
                    。current.getPath()的moveTo(event.getX(),event.getY());
// current.getPath()。setLastPoint(DX,DY)
// mNewPath.addPath(current.getPath());
                    mCurrentOps.put(ID,电流);
                }
            }
            }
            // mFlagZoom = TRUE;
            //}
        }
            打破;        案例MotionEvent.ACTION_MOVE:{            //对于(中间体p值= 0; P&下; pointerCount,P ++){            如果(mFlagDrawing ==真){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度/ *浮动DX = event.getX();
                    浮DY = event.getY();;                    如果(mScaleFactor == 1.F){
                        DX = event.getX() - mPosX;
                        DY = event.getY() - mPosY;
                    }
// mFalgPath = TRUE;
                    path.lineTo(DX,DY); * /            }否则如果(mFlagDrawing == FALSE){
// mFalgPath = TRUE;
//矩形RECT =新的矩形();                如果(mFlagDrawAgain ==真){
                        浮DX = event.getX();
                        浮DY = event.getY();                        最终诠释ID = MotionEventCompat.getPointerId(事件,0);
                        DrawOp电流= mCurrentOps.get(ID);                        如果(mScaleFactor == 1.F){
                            DX = event.getX() - mPosX;
                            DY = event.getY() - mPosY;
                        }                        p1.lineTo(DX,DY);
                        /*p1.addPath(current.getPath());*/
                        /*path.lineTo(dx,DY);
                        mNewPath.addPath(路径); * /
                }
                其他{
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                最终诠释ID = MotionEventCompat.getPointerId(事件,0);                DrawOp电流= mCurrentOps.get(ID);                最终诠释historySize = event.getHistorySize();
                对于(INT H = 0; H< historySize; H ++){
                    X = event.getHistoricalX(H);
                    Y = event.getHistoricalY(H);
                    。current.getPath()了lineTo(X,Y);// mNewPath.addPath(current.getPath());
// mNewPath.lineTo(X,Y);
                }
                X = MotionEventCompat.getX(事件,0);
                Y = MotionEventCompat.getY(事件,0);
                。current.getPath()了lineTo(X,Y);                }
            }
// path.lineTo(X,Y);
                //}
        }
            打破;        案例MotionEvent.ACTION_UP:
            //情况MotionEventCompat.ACTION_POINTER_UP:
            // {
            如果(mFlagDrawing ==真){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度
                mActivePointerId = INVALID_POINTER_ID;            }否则如果(mFlagDrawing == FALSE){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                为(中间体p值= 0; P&下; pointerCount,P ++){
                    最终诠释ID = MotionEventCompat.getPointerId(事件,P);
                    mDrawOps.push(mCurrentOps.get(ID));
                    mCurrentOps.remove(ID);
                    //}
                    updateLayer();
                }
            }
            //}
            打破;        案例MotionEvent.ACTION_CANCEL:{            如果(mFlagDrawing ==真){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度
                 mActivePointerId = INVALID_POINTER_ID;
            }否则如果(mFlagDrawing == FALSE){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                为(中间体p值= 0; P&下; pointerCount,P ++){
                    mCurrentOps
                            卸下摆臂(MotionEventCompat.getPointerId(事件,P));
                }
            }
            // mFlagZoom = TRUE;
            //}
        }
            打破;        案例MotionEvent.ACTION_POINTER_UP:{               最终诠释pointerIndex =(event.getAction()及MotionEvent.ACTION_POINTER_INDEX_MASK)GT;> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
               最终诠释pointerId = event.getPointerId(pointerIndex);
               如果(pointerId == mActivePointerId){
                //这是我们活跃的指针往上走。选择一个新的
                //活跃的指针和相应的调整。
                最终诠释newPointerIndex = pointerIndex == 0? 1:0;
                mLastTouchX = event.getX(newPointerIndex)/ mScaleFactor;
                mLastTouchY = event.getY(newPointerIndex)/ mScaleFactor;
                mActivePointerId = event.getPointerId(newPointerIndex);
               }
               打破;
              }
        默认:
            返回false;
        }        无效();        返回true;
    }
    @覆盖
    保护无效onSizeChanged(INT W,INT小时,INT oldW,诠释oldH){
        super.onSizeChanged(W,H,oldW,oldH);        如果(mLayerBitmap == NULL){
             mLayerBitmap = Bitmap.createBitmap(W,H,Bitmap.Config.ARGB_8888);
            }其他{
                位图临时= Bitmap.createScaledBitmap(mLayerBitmap,W,H,真正的);
                mLayerBitmap =临时的;
            }
         mLayerCanvas =新的Canvas(mLayerBitmap);    }    私人无效updateLayer(){
        mLayerCanvas.drawColor(0,PorterDuff.Mode.CLEAR);
        对于(DrawOp drawOp:mDrawOps){
            如果(drawOp!= NULL){
                drawOp.draw(mLayerCanvas);
            }
        }
        无效();
    }    @燮pressWarnings(空)
    @覆盖
    保护无效的onDraw(帆布油画){
        super.onDraw(画布);        如果(isInEditMode()){
            返回;
        }        canvas.save();
        canvas.scale(mScaleFactor,mScaleFactor,focusX,focusY);
        canvas.translate(mPosX,mPosY);        canvas.drawBitmap(mLayerBitmap,0,0,NULL);
        如果(mScaleFactor!= 1.F)
            canvas.restore();         如果(mScaleFactor == 1.F)
            canvas.restore();            如果(mFlagDrawAgain ==真){
// canvas.drawPath(路径,mDefaultPaint);                canvas.drawPath(P1,mDefaultPaint);
            }
            其他{
                 的for(int i = 0; I< mCurrentOps.size();我++){                        DrawOp电流= mCurrentOps.valueAt(ⅰ);
                        如果(电流!= NULL){                        current.draw(画布);
                        }                    }
            }
        canvas.restore();
    }    公共无效operationClear(){
        path.reset();
        mDrawOps.clear();
        mUndoOps.clear();
        mCurrentOps.clear();
        updateLayer();
    }    公共无效operationUndo(){
        如果(mDrawOps.size()大于0){
            mUndoOps.push(mDrawOps.pop());
            updateLayer();
        }
    }    公共无效operationRedo(){
        如果(mUndoOps.size()大于0){
            mDrawOps.push(mUndoOps.pop());
            updateLayer();
        }
    }    公共无效setPaintStrokeWidth(浮动widthPx){
        mDefaultPaint.setStrokeWidth(widthPx);
    }    公共无效setPaintOpacity(INT百分比){
        INT alphaValue =(INT)Math.round(百分比*(255.0 / 100.0));
        mDefaultPaint.setColor(combineAlpha(mDefaultPaint.getColor(),
                alphaValue));
    }    公共无效setPaintColor(串色){
        mDefaultPaint.setColor(combineAlpha(Color.parseColor(颜色),mDefaultPaint.getAlpha()));
    }    公共无效setPaintColor(INT颜色){
        mDefaultPaint.setColor(combineAlpha(颜色,mDefaultPaint.getAlpha()));
    }    公共无效setPaintMaskFilter(MaskFilter将过滤器){
        mDefaultPaint.setMaskFilter(过滤器);
    }    公共无效setPaintShader(BitmapShader着色器){
        mDefaultPaint.setShader(着色器);
    }    公共无效setPaintColorFilter(ColorFilter colorFilter){
        mDefaultPaint.setColorFilter(colorFilter);
    }    私有静态诠释combineAlpha(INT颜色,诠释阿尔法){
        返回(彩&安培;至0x00FFFFFF)| ((阿尔法&安培;为0xFF)LT;< 24);
    }    私有静态类DrawOp {
        私人最终油漆mPaint =新的油漆(Paint.ANTI_ALIAS_FLAG);
        私人最终路径的mpath =新路径();        公共DrawOp(涂料粉刷){
            复位(油漆);
        }        无效复位(涂料粉刷){
            mPath.reset();
            更新(油漆);
        }        无效更新(涂料粉刷){
            mPaint.set(油漆);
        }        无效平局(帆布油画){
            canvas.drawPath(的mpath,mPaint);
        }        公共路径的getPath(){
            返回的mpath;
        }
    }
    公共无效fillShapeColor(){    }     私有类ScaleListener扩展
       ScaleGestureDetector.SimpleOnScaleGestureListener {
      @覆盖
      公共布尔onScaleBegin(ScaleGestureDetector检测器){       //浮X = detector.getFocusX();
       //浮动Y = detector.getFocusY();       lastFocusX = -1;
       lastFocusY = -1;       返回true;
      }      @覆盖
      公共布尔onScale(ScaleGestureDetector检测器){
       mScaleFactor * = detector.getScaleFactor();       focusX = detector.getFocusX();
       focusY = detector.getFocusY();
       如果(lastFocusX == -1)
        lastFocusX = focusX;
       如果(lastFocusY == -1)
        lastFocusY = focusY;       mPosX + =(focusX - lastFocusX);
       mPosY + =(focusY - lastFocusY);
       Log.v(嗨缩放,因子:+ mScaleFactor);
       //不要让对象获取过小或过大。
       mScaleFactor = Math.max(1.F,Math.min(mScaleFactor,2.0F));       lastFocusX = focusX;
       lastFocusY = focusY;       无效();
       返回true;
      }
     }    公共无效setDrawingFlag(布尔标志){
//的System.out.println(之前设置MFLAG+ mFlagDrawing);
        this.mFlagDrawing =标志;
//的System.out.println(后设置MFLAG+ mFlagDrawing);
    }    公共无效setDrawPath(布尔标志){
        this.mFalgPath =标志;
    }
    公共无效setDrawAgain(布尔标志){
        this.mFlagDrawAgain =标志;
    }}


解决方案

在大量的研究,我发现解决方案,用于移动用手指实际帆布和用于ZoomControlButton进行放大和缩小画布。我在这里发布我的code有人帮忙。

  @覆盖
保护无效的onDraw(帆布油画){
    super.onDraw(画布);    如果(isInEditMode()){
        返回;
    }    如果(mScaleFactor == 1.F)
    canvas.save();
    canvas.drawRGB(224,224,224);
    canvas.translate(-mPosX,-mPosY);
    canvas.drawBitmap(mLayerBitmap,新的Matrix(),mDefaultPaint);    Log.v(的onDraw,规模F:+ mScaleFactor);    的for(int i = 0; I< mCurrentOps.size();我++){
        Log.v(的onDraw,当前OPS);
        DrawOp电流= mCurrentOps.valueAt(ⅰ);
        如果(电流!= NULL){
            current.draw(画布);
        }
    }
    canvas.restore();
}

在onTouch()我用下面的code

  @覆盖
    公共布尔onTouchEvent(@NonNull MotionEvent事件){        最终诠释pointerCount = MotionEventCompat.getPointerCount(事件);        开关(MotionEventCompat.getActionMasked(事件)){
        //开关(event.getAction()){
        //开关(event.getAction()及MotionEvent.ACTION_MASK){        案例MotionEvent.ACTION_DOWN:
        //情况MotionEventCompat.ACTION_POINTER_DOWN:
        {
            如果(mFlagDrawing ==真){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度            }否则如果(mFlagDrawing == FALSE){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);                浮DX = event.getX();
                浮DY = event.getY();                如果(mScaleFactor == 1.F){
                    DX = event.getX() - mPosX;
                    DY = event.getY() - mPosY;
                }                为(中间体p值= 0; P&下; pointerCount,P ++){
                    最终诠释ID = MotionEventCompat.getPointerId(事件,P);
                    DrawOp电流=新DrawOp(mDefaultPaint);
                    。current.getPath()的moveTo(event.getX()+ mPosX,event.getY()+ mPosY);
                    mCurrentOps.put(ID,电流);
                }
            }
        }
            打破;        案例MotionEvent.ACTION_MOVE:{            //对于(中间体p值= 0; P&下; pointerCount,P ++){            如果(mFlagDrawing ==真){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度            }否则如果(mFlagDrawing == FALSE){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                最终诠释ID = MotionEventCompat.getPointerId(事件,0);                DrawOp电流= mCurrentOps.get(ID);                最终诠释historySize = event.getHistorySize();
                对于(INT H = 0; H< historySize; H ++){
                    X = event.getHistoricalX(H)+ mPosX;
                    Y = event.getHistoricalY(H)+ mPosY;
                    。current.getPath()了lineTo(X,Y);
                }
                X = MotionEventCompat.getX(事件,0)+ mPosX;
                Y = MotionEventCompat.getY(事件,0)+ mPosY;
                。current.getPath()了lineTo(X,Y);                }
            }            打破;        案例MotionEvent.ACTION_UP:
            //情况MotionEventCompat.ACTION_POINTER_UP:
            // {
            如果(mFlagDrawing ==真){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度
                mActivePointerId = INVALID_POINTER_ID;            }否则如果(mFlagDrawing == FALSE){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                为(中间体p值= 0; P&下; pointerCount,P ++){
                    最终诠释ID = MotionEventCompat.getPointerId(事件,P);
                    mDrawOps.push(mCurrentOps.get(ID));
                    mCurrentOps.remove(ID);
                    //}
                    updateLayer();
                }
            }
            //}
            打破;        案例MotionEvent.ACTION_CANCEL:{            如果(mFlagDrawing ==真){                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                // code代表开始放大
                // detector.onTouchEvent(事件);
                mScaleDetector.onTouchEvent(事件);
                // code的放大光洁度
                 mActivePointerId = INVALID_POINTER_ID;
            }否则如果(mFlagDrawing == FALSE){
                的System.out.println(mFlagDrawing:+ mFlagDrawing);
                为(中间体p值= 0; P&下; pointerCount,P ++){
                    mCurrentOps
                            卸下摆臂(MotionEventCompat.getPointerId(事件,P));
                }
            }
            // mFlagZoom = TRUE;
            //}
        }
            打破;        默认:
            返回false;
        }        无效();        返回true;
    }

在更新整个层,然后我用语法如下:

 私人无效updateLayer(){
        mLayerCanvas.drawColor(0,PorterDuff.Mode.CLEAR);        mLayerCanvas.drawRGB(255,255,255);
        mLayerCanvas.save();        对于(DrawOp drawOp:mDrawOps){
            如果(drawOp!= NULL){
                drawOp.draw(mLayerCanvas);
            }
        }
        mLayerCanvas.restore();
        无效();
    }

Can any body have solution regarding how to draw on canvas using finger after zoom in and zoom out? I done pinch to zoom for canvas but stucking point is not draw right coordinate. I done more R&D from google. I have CustomView Class which i share on below.

public class DrawingView extends View {

    ArrayList<Path> pathList = new ArrayList<Path>();

    Rect mRect = new Rect();


    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;

     boolean mFalgPath=false;

     boolean mFlagDrawAgain;

     float sy;
     float sx;
     public static Context context;
     Path path = new Path();
     MyPath p1 = new MyPath();
     MyPath p2 = new MyPath();

     Path mNewPath = new Path();
//   -------------------------------------


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

        /*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) {
        /* float j = event.getX() / mScaleFactor + mRect.left;
         float k = event.getY() / mScaleFactor + mRect.top;*/

        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) {


                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
                mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish

    /*          float dx = event.getX();
                float dy = event.getY();

                if(mScaleFactor==1.f){
                    dx = event.getX() - mPosX;
                    dy = event.getY() - mPosY;
                }
//              tempPath = new Path();
                DrawOp current = new DrawOp(mDefaultPaint);
                current.getPath().moveTo(dx, dy);*/

            } else if (mFlagDrawing == false) {
                DrawOp currentNew = new DrawOp(mDefaultPaint);

                if(mFlagDrawAgain == true){
                    p1.moveTo(event.getX(), event.getY());
                /*  path.moveTo(event.getX(), event.getY());
                    mNewPath.addPath(path);*/
                }
                else{
                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());
//                  current.getPath().setLastPoint(dx, dy)
//                  mNewPath.addPath(current.getPath());
                    mCurrentOps.put(id, current);
                }
            }
            }
            // mFlagZoom = true;
            // }
        }
            break;

        case MotionEvent.ACTION_MOVE: {

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

            if (mFlagDrawing == true) {

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
                mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish

/*               float dx = event.getX();
                    float dy = event.getY();;

                    if(mScaleFactor==1.f){
                        dx = event.getX() - mPosX;
                        dy = event.getY() - mPosY;
                    }
//                  mFalgPath = true;
                    path.lineTo(dx, dy);*/

            } else if (mFlagDrawing == false) {
//              mFalgPath = true;
//              Rect rect = new Rect();

                if(mFlagDrawAgain == true){
                        float dx = event.getX();
                        float dy = event.getY();

                        final int id = MotionEventCompat.getPointerId(event, 0);
                        DrawOp current = mCurrentOps.get(id);

                        if(mScaleFactor==1.f){
                            dx = event.getX() - mPosX;
                            dy = event.getY() - mPosY;
                        }

                        p1.lineTo(dx, dy);
                        /*p1.addPath(current.getPath());*/
                        /*path.lineTo(dx, dy);
                        mNewPath.addPath(path);*/
                }
                else{
                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);

//                  mNewPath.addPath(current.getPath());
//                  mNewPath.lineTo(x, y);
                }
                x = MotionEventCompat.getX(event, 0);
                y = MotionEventCompat.getY(event, 0);
                current.getPath().lineTo(x, y);

                }
            }
//              path.lineTo(x, y);
                // }
        }
            break;

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

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
                mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
                mActivePointerId = INVALID_POINTER_ID;

            } 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) {

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
                mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
                 mActivePointerId = INVALID_POINTER_ID;
            } 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);

        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);

    }

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

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

        if (isInEditMode()) {
            return;
        }

        canvas.save();
        canvas.scale(mScaleFactor, mScaleFactor, focusX, focusY);
        canvas.translate(mPosX, mPosY);

        canvas.drawBitmap(mLayerBitmap, 0, 0, null);
        if(mScaleFactor!=1.f)
            canvas.restore();

         if(mScaleFactor==1.f)
            canvas.restore();

            if(mFlagDrawAgain == true){
//              canvas.drawPath(path, mDefaultPaint);

                canvas.drawPath(p1, mDefaultPaint);
            }
            else{
                 for (int i = 0; i < mCurrentOps.size(); i++) {

                        DrawOp current = mCurrentOps.valueAt(i);
                        if (current != null) {

                        current.draw(canvas);
                        }

                    }
            }


        canvas.restore();
    }

    public void operationClear() {
        path.reset();
        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 final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private final Path mPath = new Path();

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

        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 void fillShapeColor(){



    }

     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(1.f, Math.min(mScaleFactor, 2.0f));

       lastFocusX = focusX;
       lastFocusY = focusY;

       invalidate();
       return true;
      }
     }

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

    public void setDrawPath(boolean flag){
        this.mFalgPath = flag;
    }


    public void setDrawAgain(boolean flag){
        this.mFlagDrawAgain = flag;
    }

}
解决方案

After lots of research i found solution for moving actual canvas with finger and used ZoomControlButton for zoom in and zoom out canvas. I post my code here for someone help.

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

    if (isInEditMode()) {
        return;
    }

    if (mScaleFactor == 1.f)
    canvas.save();
    canvas.drawRGB(224, 224, 224);
    canvas.translate(-mPosX, -mPosY);
    canvas.drawBitmap(mLayerBitmap, new Matrix(), mDefaultPaint);

    Log.v("onDraw", "scale f : " + mScaleFactor);

    for (int i = 0; i < mCurrentOps.size(); i++) {
        Log.v("onDraw", "current ops");
        DrawOp current = mCurrentOps.valueAt(i);
        if (current != null) {
            current.draw(canvas);
        }
    }
    canvas.restore();
}

In onTouch() i used following code

@Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {

        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) {


                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);

                float dx = event.getX();
                float dy = event.getY();

                if(mScaleFactor==1.f){
                    dx = event.getX() - mPosX;
                    dy = event.getY() - mPosY;
                }

                for (int p = 0; p < pointerCount; p++) {
                    final int id = MotionEventCompat.getPointerId(event, p);
                    DrawOp current = new DrawOp(mDefaultPaint);
                    current.getPath().moveTo(event.getX() + mPosX, event.getY() + mPosY);
                    mCurrentOps.put(id, current);
                }
            }
        }
            break;

        case MotionEvent.ACTION_MOVE: {

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

            if (mFlagDrawing == true) {

                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) + mPosX;
                    y = event.getHistoricalY(h) + mPosY;
                    current.getPath().lineTo(x, y);
                }
                x = MotionEventCompat.getX(event, 0) + mPosX;
                y = MotionEventCompat.getY(event, 0) + mPosY;
                current.getPath().lineTo(x, y);

                }
            }

            break;

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

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
                mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
                mActivePointerId = INVALID_POINTER_ID;

            } 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) {

                System.out.println("mFlagDrawing: " + mFlagDrawing);
                // Code for Zoom start
                // detector.onTouchEvent(event);
                mScaleDetector.onTouchEvent(event);
                // Code for Zoom finish
                 mActivePointerId = INVALID_POINTER_ID;
            } 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;

        default:
            return false;
        }

        invalidate();

        return true;
    }

When updating the whole Layer then i used following syntax:

private void updateLayer() {
        mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);

        mLayerCanvas.drawRGB(255,  255,  255);


        mLayerCanvas.save();

        for (DrawOp drawOp : mDrawOps) {
            if (drawOp != null) {
                drawOp.draw(mLayerCanvas);
            }
        }
        mLayerCanvas.restore();
        invalidate();
    }

这篇关于如何通过手指在画布上画后捏放大坐标机器人改变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 12:50