擦除画布中的绘图

时间:2017-08-08 17:15:12

标签: android android-canvas

我编写了一个带有Canvas的Android应用程序,用于使用手写笔绘图。它运作良好。当我按下手写笔的上部功能键时,我想通过刷过文本来擦除图形。正常的绘图是黑色的,所以我想用白色擦除(在黑线的顶部)。我的问题是,当我按下手写笔的上部功能键(即所有线条都是白色)时,所有线条都会改变颜色,而不是仅仅将新的绘制线条涂成白色。

另一种选择是删除路径中的元素以进行擦除。如果有人有解决方案,我也会很高兴。

布局如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    tools:context="StylusBaselineA">

    <inf.ethz.ch.affectivestudy.CanvasView
        android:id="@+id/baselineACanvas"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:textColor="#FFFFFF" />

</android.support.constraint.ConstraintLayout>

CanvasView课程如下:

public class CanvasView extends View {

    public int width;
    public int height;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Path mPathErase;
    Context context;
    private Paint mPaint;
    private Paint mPaintErase;
    private float mX, mY;
    private static final float TOLERANCE = 5;
    private boolean erase = false;

    public CanvasView(Context c, AttributeSet attrs) {
        super(c, attrs);
        context = c;

        // we set a new Path
        mPath = new Path();
        mPathErase = new Path();

        // and we set a new Paint with the desired attributes
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeWidth(4f);

        mPaintErase = new Paint();
        mPaintErase.setAntiAlias(true);
        mPaintErase.setColor(Color.WHITE);
        mPaintErase.setStyle(Paint.Style.STROKE);
        mPaintErase.setStrokeJoin(Paint.Join.ROUND);
        mPaintErase.setStrokeWidth(4f);
    }

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

        // your Canvas will draw onto the defined Bitmap
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

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

        // draw the mPath with the mPaint on the canvas when onDraw
        if (erase) {
            canvas.drawPath(mPathErase, mPaintErase);
        } else {
            canvas.drawPath(mPath, mPaint);
        }
    }

    // when ACTION_DOWN start touch according to the x,y values
    private void startTouch(float x, float y) {
        if (erase) {
            mPathErase.moveTo(x, y);
        } else {
            mPath.moveTo(x, y);
        }
        mX = x;
        mY = y;
    }

    // when ACTION_MOVE move touch according to the x,y values
    private void moveTouch(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOLERANCE || dy >= TOLERANCE) {
            if (erase) {
                mPathErase.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            } else {
                mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            }
            mX = x;
            mY = y;
        }
    }

    public void clearCanvas() {
        mPath.reset();
        mPathErase.reset();
        invalidate();
    }

    // when ACTION_UP stop touch
    private void upTouch() {
        if (erase) {
            mPathErase.lineTo(mX, mY);
        } else {
            mPath.lineTo(mX, mY);
        }
    }

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

        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_ERASER) {
            // Upper function key of stylus
            erase = true;
        } else if (event.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER) {
            // Touch input
            erase = false;
            return false;
        } else {
            erase = false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startTouch(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                moveTouch(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                upTouch();
                invalidate();
                break;
        }
        return true;
    }
}

1 个答案:

答案 0 :(得分:2)

试试这个。

    public class CanvasActivity extends AppCompatActivity {

    private Paint mPaint;

    View mView;
    Button clear;
    private Canvas mCanvas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_canvas);

        RelativeLayout layout = (RelativeLayout) findViewById(R.id.Linear_layout);
        mView = new DrawingView(this);
        layout.addView(mView, new LayoutParams(
                RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.MATCH_PARENT));

        clear= (Button) findViewById(R.id.clear);
        clear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    mCanvas.drawColor(Color.WHITE);
            }
        });

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.GREEN);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(12);


    }

    public class DrawingView extends View {

        public int width;
        public  int height;
        private Bitmap mBitmap;

        private Path mPath;
        private Paint   mBitmapPaint;
        Context context;
        private Paint circlePaint;
        private Path circlePath;
        public DrawingView(Context c) {
            super(c);
            context=c;
            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);
            circlePaint = new Paint();
            circlePath = new Path();
            circlePaint.setAntiAlias(true);
            circlePaint.setColor(Color.BLUE);
            circlePaint.setStyle(Paint.Style.STROKE);
            circlePaint.setStrokeJoin(Paint.Join.MITER);
            circlePaint.setStrokeWidth(4f);
        }



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

            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);
        }

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

            canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
            canvas.drawPath( mPath,  mPaint);
            canvas.drawPath( circlePath,  circlePaint);
        }

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

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

        private void touch_move(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;

                circlePath.reset();
                circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
            }
        }

        private void touch_up() {
            mPath.lineTo(mX, mY);
            circlePath.reset();
            // 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();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }
    }
}