0

I am trying to remove my last path drawn on my canvas. I have tryed so far to add my paths in a ArrayList but I didn't find any method to remove the path easilly from canvas.

public class PaintView extends View {

    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mPaint;
    private static final int TOUCH_TOLERANCE_DP = 20;
    private static final int BACKGROUND = Color.TRANSPARENT;
    private List<Point> mPoints = new ArrayList<Point>();
    private int mLastPointIndex = 0;
    private int mTouchTolerance;
    private boolean isPathStarted = false;
    private boolean canCreatePoints = true;
    private Polygon poly;
    private Builder build;
    private ArrayList<Polygon> polyList;
    private ArrayList<Path> undoPath, redoPath;

    public PaintView(Context context) {
        super(context);
        mCanvas = new Canvas();
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(12);
        mTouchTolerance = dp2px(TOUCH_TOLERANCE_DP);

        polyList = new ArrayList<Polygon>();
        undoPath = new ArrayList<Path>();
        redoPath = new ArrayList<Path>();
    }

    @Override
    protected void onSizeChanged(int width, int height, int oldWidth,
            int oldHeight) {
        super.onSizeChanged(width, height, oldWidth, oldHeight);
        clear();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(BACKGROUND);
        canvas.drawBitmap(mBitmap, 0, 0, null);
        canvas.drawPath(mPath, mPaint);

        for(Path p : undoPath) {
            canvas.drawPath(p, mPaint);
        }

        for (Point point : mPoints) {
            canvas.drawPoint(point.x, point.y, mPaint);
        }

    }

Below is onTouch method, I create lines using Path when variable canCreatePoints it's true.If canCreatePoints it's false I check in a ArrayList<Polygon> if my touch point is inside a polygon.

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

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
    if(canCreatePoints == true)
    {
        create_point(x,y);

        if( mPoints.size() > 1 )
        {
            // start point
            Point p = mPoints.get(mLastPointIndex);
            mPath.moveTo(p.x, p.y);
            // end point
            p = mPoints.get(mLastPointIndex + 1);
            mPath.lineTo(p.x, p.y);
            mCanvas.drawPath(mPath, mPaint);

            undoPath.add(mPath);

            mPath.reset();
            // increment point index
            ++mLastPointIndex;
        }
    }

    if(canCreatePoints == false)
    {
        Points pp = new Points(Math.round(x), Math.round(y));
        boolean contains;

        for(Polygon tempPoly:polyList){
            contains = tempPoly.contains(pp);
            if(contains == true)
            {
                Log.i("TEST","Poligonul contine punctul");
                Toast.makeText(getContext(),"Test poly "+polyList.indexOf(tempPoly), 
                        Toast.LENGTH_SHORT).show();
            }
        }

        }
        invalidate();
        break;
    }
    return true;
}

private void create_point(float x, float y){
    Point p = new Point(Math.round(x),Math.round(y));
    mPoints.add(p);
}

Bellow I finnish my polygon form by action of a Button. I create a path from last point to first point and draw it on canvas.

public void finnishDraw(){
    if( mPoints.size() > 1 )
    {
        // start point
        Point p = mPoints.get(0);
        mPath.moveTo(p.x, p.y);
        // end point
        p = mPoints.get( mPoints.size() - 1);
        mPath.lineTo(p.x, p.y);
        mCanvas.drawPath(mPath, mPaint);
        mPath.reset();
        invalidate();

        int x[] = new int[mPoints.size()];
        int y[] = new int[mPoints.size()];

        build = new Builder();

        for(int i=0 ; i<mPoints.size() ; i++)
        {
            p = mPoints.get(i);
            x[i] = p.x;
            y[i] = p.y;

            build.addVertex(new Points(x[i],y[i]));

            Log.i("TEST","Adaug la builder punctele "+x[i]+" si "+y[i]);
        }

        poly = build.build();

        polyList.add(poly);
        mPoints.clear();
        mLastPointIndex = 0;

    }
}

So far I found only a solution with a back-up Bitmap before drawing a line but I didn't understand how it really works.

Gopal Singh Sirvi
  • 4,539
  • 5
  • 33
  • 55
Marian Pavel
  • 2,726
  • 8
  • 29
  • 65

2 Answers2

0

You can't undo a drawPath on a Canvas. From the documentation:

Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window.

As you say, you need a backup Bitmap to save the state of the current Bitmap before drawing on it, for example using a Memento pattern.

Take a look at Fast undo/redo for bitmap editor when memory is limited? and Fast undo facility for bitmap editor application (the last one targetting iPhone, but the underlying idea is the same)

Another approach less memory consuming could be saving the state of the objects that you want to draw on your canvas and draw them on demand (when you need to show a partial or a full result).

Community
  • 1
  • 1
antonio
  • 18,044
  • 4
  • 45
  • 61
0

To remove the last path only apply this function:

public void clearLast(){

    if(!paths.isEmpty()) {
        backgroundColor = DEFAULT_BG_COLOR;
        int size = paths.size();
        paths.remove(paths.get(size-1));
        normal();
        invalidate();
    }
}
Robert
  • 5,278
  • 43
  • 65
  • 115
JCol 1
  • 1
  • 2