使用Android在画布上缩放和绘制线条进行查看

使用Android在画布上缩放和绘制线条进行查看,android,canvas,touch,imageview,paint,Android,Canvas,Touch,Imageview,Paint,我正在画布上工作。如下图所示,视图类用于缩放和绘制线。单击缩放按钮时,捏住缩放效果良好。但当我单击绘制按钮时,我将一个布尔值传递为true,它在手指触摸下绘制线。但在图像上绘制线后,我希望在图像的特定位置上使用此绘制线再次开始捏住缩放(使用绘图线+图像进行缩放)。 现在我想开始对图像2进行收缩缩放,如绘制图像所示。我已经尝试过搜索,但仍然没有成功。 谢谢 public类DemoView扩展了视图{ 专用静态最终浮动行程_宽度=5f; /**需要对此进行跟踪,以便脏区域可以容纳笔划**/ 专用静态

我正在画布上工作。如下图所示,视图类用于缩放和绘制线。单击缩放按钮时,捏住缩放效果良好。但当我单击绘制按钮时,我将一个布尔值传递为true,它在手指触摸下绘制线。但在图像上绘制线后,我希望在图像的特定位置上使用此绘制线再次开始捏住缩放(使用绘图线+图像进行缩放)。 现在我想开始对图像2进行收缩缩放,如绘制图像所示。我已经尝试过搜索,但仍然没有成功。 谢谢

public类DemoView扩展了视图{
专用静态最终浮动行程_宽度=5f;
/**需要对此进行跟踪,以便脏区域可以容纳笔划**/
专用静态最终浮动半冲程宽度=冲程宽度/2;
私人油漆=新油漆();
私有路径路径=新路径();
//这些矩阵将用于移动和缩放图像
矩阵=新矩阵();
矩阵savedMatrix=新矩阵();
//我们可能处于这三种状态之一
静态最终int NONE=0;
静态最终整数阻力=1;
静态最终整数缩放=0;
公共静态浮点数;
公共静态浮动价值;
专用静态最终浮点最大值\缩放=10;
int模式=无;
//记住一些关于缩放的事情
PointF start=新的PointF();
PointF mid=新的PointF();
浮动oldDist=1f;
私人浮动globalX;
全球私人浮动;
私有浮动宽度;
私人浮动高度;
/**
*通过使尽可能小的区域无效来优化绘制。
*/
私人浮动lastTouchX;
私密接触;
private final RectF dirtyRect=new RectF();
私有布尔标志;
私有位图;
私人浮动因子;
私有int-mActivePointerId;
私人浮动mPosX;
私家车;
公共演示视图(上下文、属性集属性){
超级(上下文,attrs);
paint.setAntiAlias(真);
油漆。设置颜色(颜色。黑色);
绘制.设置样式(绘制.样式.笔划);
绘制.设置行程连接(绘制.连接.圆形);
油漆。设置行程宽度(行程宽度);
bgBitmap=BitmapFactory.decodeResource(context.getResources(),R.drawable.nat);
}
@凌驾
公共空白绘制(画布){
超级绘画(画布);
canvas.save();
canvas.translate(mPosX,mPosY);
canvas.scale(mScaleFactor,mScaleFactor);
drawBitmap(bgBitmap,0,0,null);
如果(mScaleFactor!=1.f)
canvas.restore();
国际单项体育联合会(旗)
画布.绘制路径(路径,绘制);
如果(mScaleFactor==1.f)
canvas.restore();
}
/**
*删除签名。
*/
公共空间清除(){
path.reset();
//重新绘制整个视图。
使无效();
}
@凌驾
公共布尔onTouchEvent(运动事件){
float eventX=event.getX();
float eventY=event.getY();
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
国际单项体育联合会(旗){
path.moveTo(eventX,eventY);
lastTouchX=eventX;
lastTouchY=eventY;
//现在还没有终点,所以不要浪费周期使其失效。
返回true;
}否则{
savedMatrix.set(矩阵);
set(event.getX(),event.getY());
模式=拖动;
MacTivePointId=event.getPointerId(0);
打破
}
case MotionEvent.ACTION\u指针\u向下:
oldDist=间距(事件);
如果(旧区>10f){
savedMatrix.set(矩阵);
中点(中点,事件);
模式=缩放;
}
打破
case MotionEvent.ACTION\u指针\u向上:
模式=无;
打破
case MotionEvent.ACTION\u移动:
case MotionEvent.ACTION\u UP:
国际单项体育联合会(旗){
resetDirtyRect(eventX,eventY);
//当硬件跟踪事件的速度快于事件的交付速度时,
//
//事件将包含这些跳过点的历史记录。
int historySize=event.getHistorySize();
for(int i=0;i10f){
矩阵集(savedMatrix);
浮动比例=新距离/旧距离;
矩阵。后标度(标度、标度、中x、中y);
}
//final int pointerIndex=event.findPointerIndex((整数)MacTivePointId);
//最终浮点x=event.getX(pointerIndex);
//最终浮点y=event.getY(pointerIndex);
//
//最终浮点数dx=x-全局x;
//最终浮子dy=y-全局;
//mPosX+=dx;
//mPosY+=dy;
}
}
违约:
Log.e(“忽略的触摸事件:,“i”+事件.toString());
返回false;
}
public class DemoView extends View {

    private static final float STROKE_WIDTH = 5f;

    /** Need to track this so the dirty region can accommodate the stroke. **/
    private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;

    private Paint paint = new Paint();
    private Path path = new Path();



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

        // We can be in one of these 3 states
        static final int NONE = 0;
        static final int DRAG = 1;
        static final int ZOOM = 0;
        public static float xValue;
        public static float yValue;
        private static final float MAX_ZOOM = 10;
        int mode = NONE;

        // Remember some things for zooming
        PointF start = new PointF();
        PointF mid = new PointF();
        float oldDist = 1f;
        private float globalX;
        private float globalY;
        private float width;
        private float height;

    /**
     * Optimizes painting by invalidating the smallest possible area.
     */
    private float lastTouchX;
    private float lastTouchY;
    private final RectF dirtyRect = new RectF();

    private boolean flag;

    private Bitmap bgBitmap;
    private float mScaleFactor;

    private int mActivePointerId;

    private float mPosX;

    private float mPosY;

    public DemoView(Context context, AttributeSet attrs) {
        super(context, attrs);

        paint.setAntiAlias(true);
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeWidth(STROKE_WIDTH);
        bgBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.nat);
    }
    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        canvas.save();
        canvas.translate(mPosX, mPosY);
        canvas.scale(mScaleFactor, mScaleFactor);

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

        if(flag)
            canvas.drawPath(path,paint);

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

    /**
     * Erases the signature.
     */
    public void clear() {
        path.reset();

        // Repaints the entire view.
        invalidate();
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float eventX = event.getX();
        float eventY = event.getY();


        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (flag) {
                path.moveTo(eventX, eventY);
                lastTouchX = eventX;
                lastTouchY = eventY;
                // There is no end point yet, so don't waste cycles invalidating.
                return true;
            }else{
                savedMatrix.set(matrix);
                start.set(event.getX(), event.getY());
                mode = DRAG;
                mActivePointerId = event.getPointerId(0);
                break;
            }

        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if (oldDist > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
            }
            break;
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
        case MotionEvent.ACTION_UP:
            if (flag) {
                resetDirtyRect(eventX, eventY);

                // When the hardware tracks events faster than they are delivered,
                // the
                // event will contain a history of those skipped points.
                int historySize = event.getHistorySize();
                for (int i = 0; i < historySize; i++) {
                    float historicalX = event.getHistoricalX(i);
                    float historicalY = event.getHistoricalY(i);
                    expandDirtyRect(historicalX, historicalY);
                    path.lineTo(historicalX, historicalY);
                }

                // After replaying history, connect the line to the touch point.
                path.lineTo(eventX, eventY);
                break;
            }else{
                // Start tracking the dirty region.
                if (mode == DRAG) {
                    // ...
                    matrix.set(savedMatrix);
                    matrix.postTranslate(event.getX() - start.x, event.getY()
                            - start.y);
                } else if (mode == ZOOM) {
                    float newDist = spacing(event);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        float scale = newDist / oldDist;
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
//                  final int pointerIndex = event.findPointerIndex((Integer) mActivePointerId);
//                  final float x = event.getX(pointerIndex);
//                  final float y = event.getY(pointerIndex);
//
//                  final float dx = x - globalX;
//                  final float dy = y - globalY;
//                  mPosX += dx;
//                  mPosY += dy;
                }
            }

        default:
            Log.e("Ignored touch event: " ,"i"+ event.toString());
            return false;
        }

        // Include half the stroke width to avoid clipping.
        invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
                (int) (dirtyRect.top - HALF_STROKE_WIDTH),
                (int) (dirtyRect.right + HALF_STROKE_WIDTH),
                (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

        lastTouchX = eventX;
        lastTouchY = eventY;

        return true;
    }

    /**
     * Called when replaying history to ensure the dirty region includes all
     * points.
     */
    private void expandDirtyRect(float historicalX, float historicalY) {
        if (historicalX < dirtyRect.left) {
            dirtyRect.left = historicalX;
        } else if (historicalX > dirtyRect.right) {
            dirtyRect.right = historicalX;
        }
        if (historicalY < dirtyRect.top) {
            dirtyRect.top = historicalY;
        } else if (historicalY > dirtyRect.bottom) {
            dirtyRect.bottom = historicalY;
        }
    }

    /**
     * Resets the dirty region when the motion event occurs.
     */
    private void resetDirtyRect(float eventX, float eventY) {

        // The lastTouchX and lastTouchY were set when the ACTION_DOWN
        // motion event occurred.
        dirtyRect.left = Math.min(lastTouchX, eventX);
        dirtyRect.right = Math.max(lastTouchX, eventX);
        dirtyRect.top = Math.min(lastTouchY, eventY);
        dirtyRect.bottom = Math.max(lastTouchY, eventY);
    }


    /** Determine the space between the first two fingers */
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    public boolean setFlag(boolean b) {
        return flag = b;
    }
}
 imageView.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    ImageView view = (ImageView) v;

                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        savedMatrix.set(matrix1);
                        start.set(event.getX(), event.getY());
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        oldDist = spacing(event);
                        if (oldDist > 10f) {
                            start.set(event.getX(), event.getY());
                            savedMatrix.set(matrix1);
                            midPoint(mid, event);
                            // mode = POINT2;
                            mode = ZOOM;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        mode = NONE;
                        distanceOffset = minOffset;
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        distanceOffset = minOffset;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == POINT2) {
                            newDist = spacing(event);
                            if (newDist - oldDist > 5f
                                    || newDist - oldDist < -5f) {
                                mode = ZOOM;
                            } else {
                                start.set(event.getX(), event.getY());
                                mode = DRAG;
                            }
                        } else if (mode == DRAG) {
                            matrix1.set(savedMatrix);
                            matrix1.postTranslate(event.getX() - start.x,
                                    event.getY() - start.y);
                        } else if (mode == ZOOM) {
                            newDist = spacing(event);
                            if (newDist > 10f) {
                                matrix1.set(savedMatrix);
                                float scale = newDist / oldDist;
                                matrix1.postScale(scale, scale, mid.x,
                                        mid.y);
                                finalscale = scale;
                            }
                        }
                        break;
                    }

                    view.setImageMatrix(matrix1);
    //              matrixTurning(matrix1, view);
                    return true; // indicate event was handled
                }
            });
        }



    mPaintView.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    PaintView view = (PaintView) v;
                    view.setScaleType(ImageView.ScaleType.MATRIX);
                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        if (falg) {
                            savedMatrix.set(matrix);
                            start.set(event.getX(), event.getY());
                            mode = DRAG;
                        } else {
                            view.onTouchEvent(event);
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        if (falg) {
                            oldDist = spacing(event);
                            if (oldDist > 10f) {
                                start.set(event.getX(), event.getY());
                                savedMatrix.set(matrix);
                                midPoint(mid, event);
                                mode = ZOOM;
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (falg) {
                            mode = NONE;
                            distanceOffset = minOffset;
                        }
                    case MotionEvent.ACTION_POINTER_UP:
                        if (falg) {
                            mode = NONE;
                            distanceOffset = minOffset;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (falg) {
                            if (mode == POINT2) {
                                newDist = spacing(event);
                                if (newDist - oldDist > 5f
                                        || newDist - oldDist < -5f) {
                                    mode = ZOOM;
                                } else {
                                    start.set(event.getX(), event.getY());
                                    mode = DRAG;
                                }
                            } else if (mode == DRAG) {
                                matrix.set(savedMatrix);
                                matrix.postTranslate(event.getX() - start.x,
                                        event.getY() - start.y);
                            } else if (mode == ZOOM) {
                                newDist = spacing(event);
                                if (newDist > 10f) {
                                    matrix.set(savedMatrix);
                                    float scale = newDist / oldDist;
                                    matrix.postScale(scale, scale, mid.x, mid.y);
                                    finalscale = scale;
                                }
                            }
                        } else {
                            view.onTouchEvent(event);
                        }
                        break;
                    }

                    limitZoom(matrix);
                    view.setImageMatrix(matrix);

                    matrixTurning(matrix, view);
                    RectF r = new RectF();
                    matrix.mapRect(r);
                    scaledImageOffsetX = r.left;
                    scaledImageOffsetY = r.top;

                    return true;
                }
            });
        }


        private void limitZoom(Matrix m) {

            float[] values = new float[9];
            m.getValues(values);
            float scaleX = values[Matrix.MSCALE_X];
            float scaleY = values[Matrix.MSCALE_Y];
            if(scaleX > MAX_ZOOM) {
                scaleX = MAX_ZOOM;
            } else if(scaleX < MIN_ZOOM) {
                scaleX = MIN_ZOOM;
            }

            if(scaleY > MAX_ZOOM) {
                scaleY = MAX_ZOOM;
            } else if(scaleY < MIN_ZOOM) {
                scaleY = MIN_ZOOM;
            }

            values[Matrix.MSCALE_X] = scaleX;
            values[Matrix.MSCALE_Y] = scaleY; 
            m.setValues(values);
        }

        public boolean getFlag(boolean b) {
            return falg = b;
        }
   class PaintView extends ImageView {

private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;

// onDraw
private Paint mPaint;

// onTouch
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;

public PaintView(Context context) {
    this(context, null);
}

public PaintView(Context context, AttributeSet attrs) {
    super(context, attrs);

    mBitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888);
    mPath = new Path();
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {
    // canvas.drawColor(0xFFAAAAAA);
    super.onDraw(canvas);
    mCanvas = canvas;
    // canvas = mCanvas;
     canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    // canvas.drawBitmap(mBitmap, PaintScreen.matrix, mBitmapPaint);
    canvas.drawPath(mPath, mPaint);

}

public void clear() {
    mPaint.reset();
    // invalidate();
}

public void setMPaint(Paint paint) {
    mPaint = paint;
}

private void touchStart(float x, float y) {
    // mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
}

private void touchMove(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        mX = x;
        mY = y;
    }
}

private void touchUp() {
    mPath.lineTo(mX, mY);
    // commit the path to our offscreen
    mCanvas.drawPath(mPath, mPaint);
    // kill this so we don't double draw
    mPath.reset();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    Log.d("PaintView", "ev ->" + event.getAction());

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touchStart(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        touchMove(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touchUp();
        invalidate();
        break;
    }
    return true;
}

public void cMatrix(Matrix matrix) {
    mCanvas.setMatrix(matrix);
}
}