在画布中撤消图像草图

时间:2016-05-10 07:11:15

标签: android android-studio view android-canvas undo-redo

我使用上面的代码进行撤消,但是通过调用此方法无法更新canvas。 我已经为Sketch功能创建了DrawingView类,我只需要对每个功能进行撤销,例如,1。Smoothline 2.Rectangle 3.Circle 4.Straight line etc.

public class DrawingView extends View {

    protected Path mPath = new Path();
    public static Paint mPaint;
    protected Bitmap mBitmap;
    public static Canvas mCanvas;
    public int TOUCH_TOLERANCE = 5;
    public static int lineThickness = 5;
    public static int mCurrentShape;
    public boolean isDrawing = false;
    float mx,my,mStartX,mStartY;

    private int stateToSave;

    public static Paint mPaintErase = new Paint();
    protected Path mPathErase = new Path();

    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>();

    public DrawingView(Context context) {
        super(context);
        init();
        EraseLine();
    }

    public DrawingView(Context context,AttributeSet attrs)
    {
        super(context, attrs);
        init();
        EraseLine();
    }



    /**
     * Create Path from Event.
     * @param event
     * @return
     */
    private Path createPath(MotionEvent event) {
        Path path = new Path();

        // Save for ACTION_MOVE
        this.mStartX = event.getX();
        this.mStartY = event.getY();

        path.moveTo(this.mStartX, this.mStartY);

        return path;
    }


    protected void init()
    {
        mPaint = new Paint(Paint.DITHER_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(getContext().getResources().getColor(R.color.colorYellow));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(lineThickness);

        mPath = new Path();
        paths.add(mPath);
    }

    public Bitmap getBitmap()
    {
        this.setDrawingCacheEnabled(true);
        this.buildDrawingCache();
        Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());
        this.setDrawingCacheEnabled(false);

        return bmp;
    }

    @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
    public boolean onTouchEvent(MotionEvent event)
    {
        mx = event.getX();
        my = event.getY();

        switch (mCurrentShape)
        {
            case 1:
                onTouchEventSmoothLine(event);
                break;

            case 2:

                onTouchEventErase(event);
                break;

            case 3:

                onTouchEventLine(event);
                break;

            case 4:

                onTouchEventCircle(event);
                break;

            case 5:

                onTouchEventRectangle(event);
                break;

            case 6:

                break;

            default:
                break;
        }
        return true;
    }

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

        canvas.drawBitmap(mBitmap, 0, 0, mPaint);

        if (isDrawing)
        {
            switch (mCurrentShape)
            {
                case 1:

                    break;

                case 2:

                 //   EraseLine();
                    break;

                case 3:

                    onDrawLine(canvas);
                    break;

                case 4:

                    onDrawCircle(canvas);
                    break;

                case 5:

                    onDrawRectangle(canvas);
                    break;

                case 6:

                    onDrawSmoothLine(canvas);
                    break;

                default:
                    break;
            }
        }
    }

    //------------------------------------------------------------------
    // Rectangle
    //------------------------------------------------------------------
    private void onTouchEventRectangle(MotionEvent event) {

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                invalidate();
                break;

            case MotionEvent.ACTION_UP:

                isDrawing = false;
                drawRectangle(mCanvas,mPaint);
                invalidate();
                break;
        }
    }

    private void onDrawRectangle(Canvas canvas) {
        drawRectangle(canvas, mPaint);
    }

    private void drawRectangle(Canvas canvas,Paint paint){
        float right = mStartX > mx ? mStartX : mx;
        float left = mStartX > mx ? mx : mStartX;
        float bottom = mStartY > my ? mStartY : my;
        float top = mStartY > my ? my : mStartY;
        canvas.drawRect(left, top, right, bottom, paint);
    }

    //------------------------------------------------------------------
    // Circle
    //------------------------------------------------------------------
    private void onDrawCircle(Canvas canvas) {
        canvas.drawCircle(mStartX, mStartY, calculateRadius(mStartX, mStartY, mx, my), mPaint);
    }

    private void onTouchEventCircle(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:
                invalidate();
                break;

            case MotionEvent.ACTION_UP:
                isDrawing = false;
                mCanvas.drawCircle(mStartX, mStartY,
                        calculateRadius(mStartX,mStartY,mx,my),mPaint);
                invalidate();
                break;

            default:
                break;
        }
    }

    /**
     * @return
     */
    protected float calculateRadius(float x1, float y1, float x2, float y2) {

        return (float) Math.sqrt(
                Math.pow(x1 - x2, 2) +
                        Math.pow(y1 - y2, 2)
        );
    }

    //------------------------------------------------------------------
    // Line
    //------------------------------------------------------------------
    private void onDrawLine(Canvas canvas) {

        float dx = Math.abs(mx - mStartX);
        float dy = Math.abs(my - mStartY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
        {
            canvas.drawLine(mStartX, mStartY, mx, my, mPaint);
        }
    }

    private void onTouchEventLine(MotionEvent event) {

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                isDrawing = false;
                mCanvas.drawLine(mStartX, mStartY, mx, my, mPaint);
                invalidate();
                break;
        }
    }

    //------------------------------------------------------------------
    // Smooth Line
    //------------------------------------------------------------------
    private void onDrawSmoothLine(Canvas canvas)
    {
        for (Path p : paths)
        {
            canvas.drawPath(p, mPaint);
        }
    }

    private void onTouchEventSmoothLine(MotionEvent event)
    {

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                isDrawing = true;
                mStartX = mx;
                mStartY = my;

                mPath.reset();
                mPath.moveTo(mx, my);

                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:

                float dx = Math.abs(mx - mStartX);
                float dy = Math.abs(my - mStartY);
                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                    mPath.quadTo(mStartX, mStartY, (mx + mStartX) / 2, (my + mStartY) / 2);
                    mStartX = mx;
                    mStartY = my;
                }
                mCanvas.drawPath(mPath, mPaint);
                invalidate();
                break;

            case MotionEvent.ACTION_UP:
                isDrawing = false;
                mPath.lineTo(mStartX, mStartY);
                mCanvas.drawPath(mPath, mPaint);
                mPath.reset();
                paths.add(mPath);
                invalidate();
                break;
        }
    }

    //------------------------------------------------------------------
    // Erase Line
    //------------------------------------------------------------------
    public void EraseLine()
    {
        mPaintErase.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mPaintErase.setColor(Color.TRANSPARENT);
        mPaintErase.setAntiAlias(true);
        mPaintErase.setDither(true);
        mPaintErase.setStyle(Paint.Style.STROKE);
        mPaintErase.setStrokeJoin(Paint.Join.ROUND);
        mPaintErase.setStrokeCap(Paint.Cap.ROUND);
        mPaintErase.setStrokeWidth(lineThickness);
    }

    private void onTouchEventErase(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                mPathErase.reset();
                mPathErase.moveTo(mx, my);
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                float dx = Math.abs(mx - mStartX);
                float dy = Math.abs(my - mStartY);
                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                    mPathErase.quadTo(mStartX, mStartY, (mx + mStartX) / 2, (my + mStartY) / 2);
                    mStartX = mx;
                    mStartY = my;
                }
                mCanvas.drawPath(mPathErase, mPaintErase);
                invalidate();
                break;

            case MotionEvent.ACTION_UP:

                isDrawing = false;
                mPathErase.lineTo(mStartX, mStartY);
                mCanvas.drawPath(mPathErase, mPaintErase);
                mPathErase.reset();
                invalidate();
                break;
        }
    }

    /**
     * Undo functionality.
     */
    public void onClickUndo ()
    {
        if (paths.size()>0)
        {
            paths.remove(paths.size()-1);
            invalidate();
        }
        else
        {
            Toast.makeText(getContext().getApplicationContext(),"Undo not found.",Toast.LENGTH_SHORT).show();
        }
        //toast the user
    }

    @Override
    public Parcelable onSaveInstanceState() {
        //begin boilerplate code that allows parent classes to save state
        Parcelable superState = super.onSaveInstanceState();

        SavedState ss = new SavedState(superState);
        //end

        ss.stateToSave = this.stateToSave;

        return ss;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        //begin boilerplate code so parent classes can restore state
        if(!(state instanceof SavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }

        SavedState ss = (SavedState)state;
        super.onRestoreInstanceState(ss.getSuperState());
        //end

        this.stateToSave = ss.stateToSave;
    }

    static class SavedState extends BaseSavedState {
        int stateToSave;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            this.stateToSave = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(this.stateToSave);
        }

        //required field that makes Parcelables from a Parcel
        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }
                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
    }
}

2 个答案:

答案 0 :(得分:2)

我在这里找到了解决方案并且它正常工作。

请检查此代码,了解Sketch over image的笔,线,圆,矩形和撤消功能:

package com.thefinal3.Sketch;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.thefinal3.Bean.PathBean;
import com.thefinal3.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Akash patel on 11-04-2016.
 */
public class DrawingView extends View {

    protected Path mPath = new Path();
    public static Paint mPaint;
    protected Bitmap mBitmap;
    public static Canvas mCanvas;
    public int TOUCH_TOLERANCE = 5;
    public static int lineThickness = 5;
    public static int ColorStroke;
    public static int mCurrentShape;
    public boolean isDrawing = false;
    float mx,my,mStartX,mStartY;

    private int stateToSave;

    public static Paint mPaintErase = new Paint();
    public static Paint mPaintBitmap;
    protected Path mPathErase = new Path();
    Context context;

    private ArrayList<PathBean> paths = new ArrayList<PathBean>();

    public DrawingView(Context context,AttributeSet attrs)
    {
        super(context, attrs);
        setFocusable(true);
        setFocusableInTouchMode(true);
        init();
        EraseLine();
        this.context = context;
    }

    protected void init()
    {
        mPaint = new Paint(Paint.DITHER_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(getContext().getResources().getColor(R.color.colorYellow));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(lineThickness);

        ColorStroke = mPaint.getColor();
        lineThickness = (int)mPaint.getStrokeWidth();
        mCanvas = new Canvas();
    }

    public Bitmap getBitmap()
    {
        this.setDrawingCacheEnabled(true);
        this.buildDrawingCache();
        Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());
        this.setDrawingCacheEnabled(false);

        return bmp;
    }

    @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.setBitmap(mBitmap);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        mx = event.getX();
        my = event.getY();

        switch (mCurrentShape)
        {
            case 1:
                onTouchEventSmoothLine(event);
                break;

            case 2:

           //     onTouchEventErase(event);
                break;

            case 3:

                onTouchEventLine(event);
                break;

            case 4:

                onTouchEventCircle(event);
                break;

            case 5:

                onTouchEventRectangle(event);
                break;

            default:
                break;
        }
        return true;
    }

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

        for (PathBean p : paths)
        {
            mPaint.setColor(p.getColor());
            mPaint.setStrokeWidth(p.getLineWidthStroke());
            switch (p.getDrawingType())
            {
                case 1:

                    canvas.drawPath(p.getmPath(), mPaint);
                    Log.e("onDraw ;-->", "Path Called...");
                    break;

                case 2:

                    break;

                case 3:

                    float dx1 = Math.abs(p.getMx() - p.getmStartX());
                    float dy1 = Math.abs(p.getMy() - p.getmStartY());
                    if (dx1 >= TOUCH_TOLERANCE || dy1 >= TOUCH_TOLERANCE)
                    {
                        canvas.drawLine(p.getmStartX(), p.getmStartY(), p.getMx(), p.getMy(), mPaint);
                        Log.e("onDraw ;-->", "Line Called...");
                    }
                    break;

                case 4:

                    canvas.drawCircle(p.getmStartX(), p.getmStartY(), calculateRadius(p.getmStartX(), p.getmStartY(), p.getMx(), p.getMy()), mPaint);
                    break;

                case 5:

                    float right = p.getmStartX() > p.getMx() ? p.getmStartX() : p.getMx();
                    float left = p.getmStartX() > p.getMx() ? p.getMx() : p.getmStartX();
                    float bottom =  p.getmStartY() > p.getMy() ?  p.getmStartY() : p.getMy();
                    float top =  p.getmStartY() > p.getMy() ? p.getMy() :  p.getmStartY();
                    canvas.drawRect(left, top, right, bottom,mPaint);
                    break;

                default:
                    break;
            }
        }
        mPaint.setColor(ColorStroke);
        mPaint.setStrokeWidth(lineThickness);

        if (isDrawing)
        {
            switch (mCurrentShape)
            {
                case 1:

                    canvas.drawPath(mPath, mPaint);
                    break;

                case 2:

                    break;

                case 3:

                    onDrawLine(canvas);
                    break;

                case 4:

                    onDrawCircle(canvas);
                    break;

                case 5:

                    onDrawRectangle(canvas);
                    break;

                default:
                    break;
            }
        }
    }

    //------------------------------------------------------------------
    // Rectangle
    //------------------------------------------------------------------
    private void onTouchEventRectangle(MotionEvent event) {

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                invalidate();
                break;

            case MotionEvent.ACTION_UP:

                isDrawing = false;
                drawRectangle(mCanvas,mPaint);
                PathBean bean = new PathBean();
                bean.setColor(ColorStroke);
                bean.setLineWidthStroke(lineThickness);
                bean.setmStartX(mStartX);
                bean.setmStartY(mStartY);
                bean.setMx(mx);
                bean.setMy(my);
                bean.setDrawingType(5);
                paths.add(bean);
                invalidate();
                break;
        }
    }

    private void onDrawRectangle(Canvas canvas) {
        drawRectangle(canvas, mPaint);
    }

    private void drawRectangle(Canvas canvas,Paint paint){
        float right = mStartX > mx ? mStartX : mx;
        float left = mStartX > mx ? mx : mStartX;
        float bottom = mStartY > my ? mStartY : my;
        float top = mStartY > my ? my : mStartY;
        canvas.drawRect(left, top, right, bottom, paint);
    }

    //------------------------------------------------------------------
    // Circle
    //------------------------------------------------------------------
    private void onDrawCircle(Canvas canvas) {
        canvas.drawCircle(mStartX, mStartY, calculateRadius(mStartX, mStartY, mx, my), mPaint);
    }

    private void onTouchEventCircle(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                invalidate();
                break;

            case MotionEvent.ACTION_UP:

                isDrawing = false;
                mCanvas.drawCircle(mStartX, mStartY,
                        calculateRadius(mStartX, mStartY, mx, my), mPaint);
                PathBean bean = new PathBean();
                bean.setColor(ColorStroke);
                bean.setLineWidthStroke(lineThickness);
                bean.setmStartX(mStartX);
                bean.setmStartY(mStartY);
                bean.setMx(mx);
                bean.setMy(my);
                bean.setDrawingType(4);
                paths.add(bean);
                invalidate();
                break;

            default:
                break;
        }
    }

    /**
     * @return
     */
    protected float calculateRadius(float x1, float y1, float x2, float y2) {

        return (float) Math.sqrt(
                Math.pow(x1 - x2, 2) +
                        Math.pow(y1 - y2, 2)
        );
    }

    //------------------------------------------------------------------
    // Line
    //------------------------------------------------------------------
    private void onDrawLine(Canvas canvas) {

        float dx = Math.abs(mx - mStartX);
        float dy = Math.abs(my - mStartY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
        {
            canvas.drawLine(mStartX, mStartY, mx, my, mPaint);
        }
    }

    private void onTouchEventLine(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                invalidate();
                break;

            case MotionEvent.ACTION_UP:

                isDrawing = false;
                mCanvas.drawLine(mStartX, mStartY, mx, my, mPaint);
                PathBean bean = new PathBean();
                bean.setColor(ColorStroke);
                bean.setLineWidthStroke(lineThickness);
                bean.setmStartX(mStartX);
                bean.setmStartY(mStartY);
                bean.setMx(mx);
                bean.setMy(my);
                bean.setDrawingType(3);
                paths.add(bean);
                invalidate();
                break;
        }
    }

    //------------------------------------------------------------------
    // Smooth Line
    //------------------------------------------------------------------
    private void onDrawSmoothLine(Canvas canvas) {

        for (PathBean p : paths)
        {
            mPaint.setColor(p.getColor());
            canvas.drawPath(p.getmPath(), mPaint);
        }
        mPaint.setColor(ColorStroke);
        canvas.drawPath(mPath, mPaint);
    }

    private void onTouchEventSmoothLine(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;

                mPath.reset();
                mPath.moveTo(mx, my);
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                float dx = Math.abs(mx - mStartX);
                float dy = Math.abs(my - mStartY);
                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                    mPath.quadTo(mStartX, mStartY, (mx + mStartX) / 2, (my + mStartY) / 2);
                    mStartX = mx;
                    mStartY = my;
                }
                mCanvas.drawPath(mPath, mPaint);
                invalidate();
                break;

            case MotionEvent.ACTION_UP:
                isDrawing = false;
                mPath.lineTo(mStartX, mStartY);
                mCanvas.drawPath(mPath, mPaint);
         //       mPath.reset();
                PathBean bean = new PathBean();
                bean.setmPath(mPath);
                bean.setColor(mPaint.getColor());
                bean.setLineWidthStroke((int)mPaint.getStrokeWidth());
                bean.setDrawingType(1);
                paths.add(bean);
                mPath = new Path();
                invalidate();
                break;
        }
    }

    //------------------------------------------------------------------
    // Erase Line
    //------------------------------------------------------------------
    public void EraseLine()
    {
        mPaintErase.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mPaintErase.setColor(Color.TRANSPARENT);
        mPaintErase.setAntiAlias(true);
        mPaintErase.setDither(true);
        mPaintErase.setStyle(Paint.Style.STROKE);
        mPaintErase.setStrokeJoin(Paint.Join.ROUND);
        mPaintErase.setStrokeCap(Paint.Cap.ROUND);
        mPaintErase.setStrokeWidth(lineThickness);

        mPaintBitmap = new Paint(Paint.DITHER_FLAG);
    }

    private void onTouchEventErase(MotionEvent event)
    {
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:

                isDrawing = true;
                mStartX = mx;
                mStartY = my;
                mPathErase.reset();
                mPathErase.moveTo(mx, my);
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:

                float dx = Math.abs(mx - mStartX);
                float dy = Math.abs(my - mStartY);
                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                    mPathErase.quadTo(mStartX, mStartY, (mx + mStartX) / 2, (my + mStartY) / 2);
                    mStartX = mx;
                    mStartY = my;
                }
                mCanvas.drawPath(mPathErase, mPaintErase);
                invalidate();
                break;

            case MotionEvent.ACTION_UP:

                isDrawing = false;
                mPathErase.lineTo(mStartX, mStartY);
                mCanvas.drawPath(mPathErase, mPaintErase);
             //   mPathErase.reset();
                PathBean bean = new PathBean();
                bean.setmPath(mPathErase);
                bean.setLineWidthStroke(lineThickness);
                bean.setDrawingType(2);
                paths.add(bean);
                mPathErase = new Path();
                invalidate();
                break;
        }
    }

    /**
     * Undo functionality.
     */
    public void onClickUndo ()
    {
        if (paths.size()>0)
        {
            paths.remove(paths.size()-1);
            invalidate();
        }
        else
        {
            Toast.makeText(getContext().getApplicationContext(),"There is no undo action found.",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public Parcelable onSaveInstanceState() {
        //begin boilerplate code that allows parent classes to save state
        Parcelable superState = super.onSaveInstanceState();

        SavedState ss = new SavedState(superState);
        //end

        ss.stateToSave = this.stateToSave;

        return ss;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        //begin boilerplate code so parent classes can restore state
        if(!(state instanceof SavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }

        SavedState ss = (SavedState)state;
        super.onRestoreInstanceState(ss.getSuperState());
        //end

        this.stateToSave = ss.stateToSave;
    }

    static class SavedState extends BaseSavedState {
        int stateToSave;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            this.stateToSave = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(this.stateToSave);
        }

        //required field that makes Parcelables from a Parcel
        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }
                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
    }
}

答案 1 :(得分:0)

你绘制所有的圆圈,对位图进行处理,并且位图不会自行擦除。因此当你从路径中删除路径并使视图无效时,它只会在位图上绘制一个叠加层。

你需要通过将paint的颜色设置为backgroundColor来擦除位图,并在每次需要撤消时调用mCanvas.drawRect(0,0,mBitmap.getWidth(),mBitmap.getHeight(),mPaint)动作,然后你可以重绘剩余的路径。