2

hi i am trying to add undo feature to finger paint example given in API demo. but i am not able to achieve it. So far i have added all the path that are drawn in a list and redrawing it to the canvas except the last path. But it is not working. Any clue where i am going wrong.

Edit #1: My Undo Method is this

private void undo(){            
        if (MyPathList.size()>0) {
            mCanvas.drawColor(0xFFFFFFFF);


            for (int i = 0; i < MyPathList.size()-1; i++) {
                Path p=(Path)MyPathList.get(i);             
                mCanvas.drawLine(0, 0, 20, 20, mPaint);
                mCanvas.drawLine(0, 0, 80, 20, mPaint);
                mCanvas.drawPath(p, mPaint);
                p.reset();              
            }               
            invalidate();
        }           
    }

Thanks in Advance.

Dinash
  • 2,967
  • 4
  • 31
  • 45

3 Answers3

2

Maybe this tutorial is what your looking for: http://www.tutorialforandroid.com/p/drawing-with-canvas-series.html

Terence Lui
  • 2,758
  • 1
  • 17
  • 17
  • i have already went through that and they have used some design pattern over there. My Main question is why the above code is working... and is there any other easy way to go about it. – Dinash Oct 03 '11 at 10:01
  • Once you draw onto the canvas, the draw is stuck right at the canvas. You need to clear the canvas when you want an update, just like the tutorial above. Thinking it like a page-flipping cartoon. you have to draw each page same image with minor differences. And on Android or other programming languages, you get 1 page, and all you can do is clear the canvas and redraw. You may wonder what canvas.save and canvas.restore do. http://stackoverflow.com/questions/3051981/why-do-we-use-canvas-save-or-canvas-restore here you would get the idea. – Terence Lui Oct 04 '11 at 02:27
1

When you drawing line for the current process like at now use drawing the like using it finger now store this points into temp_array list. now add this temp_array list into the main array list which will draw all sub array list point like wise here.

List<List<Point> main_Points = new ArrayList<List<Point>>();
List<Point> temp_point; // this one is for the current drawing

like onTouch()

onTouch(MotionEvent event){
     int x = (int) event.getX();
     int y = (int) event.getY();

     if(event.getAction==MotionEvent.DOWN){
           temp_point = new ArrayList<Point>();
           temp_point.add(new Point(x,y);
     }else if(event.getAction==MotionEvent.MOVE){
           if(temp_point!=null)
              temp_point.add(new Point(x,y);
     }else if(event.getAction==MotionEvent.UP){
           mainPoint.add(temp_point);
           temp_point = null;
     }
     return true;
}

always re-initialize into onTouch() method in down event and get all the point at move time get the point and store into this list now at up event time store this array list into main list.

now if you want to undo last or more you can just remove last add temp_point list from the mainPoint array List

Pratik
  • 30,557
  • 17
  • 84
  • 156
  • 1+ for the answer... and it works fine... but in case of an arc... how to go about it... and when gathering the points it's not returning the continuous points instead three points for long line and two points for the short line... – Dinash Oct 04 '11 at 05:45
0
There is another way of achieving undo , you can use porterduff mode.clear to draw over the particular path which need to be undone

  1.    Store your paths to  array of Paths during onTouch event. 

   2.   check the size of stored path array,  and get the last drawn path   using size() method. i.e patharray.size()-1;
  3.    Store that to a separate path. 
  4.    Call invalidate() method
  5.    Set your paint xfermode property to Mode.clear
  6.    Draw on canvas using the retrieved path and the newly set paint. 



    Public Path unDonePath,drawpath;
    Public Boolean undo=false;
    Paint paintForUndo= new Paint();
    Public ArrayList<Path>unDonePathArray= new ArrayList<Path>();
    Public ArrayList<Path>patharray= new ArrayList<Path>();
    public boolean onTouchEvent(MotionEvent event) 
    {
    Switch(MotionEven.getAction())
    {
    case MotionEvent.ACTION_UP:
    pathArray.add(drawpath);
    pathToDraw = new Path();
    //drawpath contains touchx and touch y co-ordinates.
    }
    }
   Protected void undo()
   {
   if(pathArray.size()>0) {
   unDonePath=new Path();
   unDonePathArray.add(pathArray.remove(pathArray.size()-1));
   unDonePath=unDonePathArray.get(unDonePathArray.size()-1);
   unDonePathArray.clear();
   invalidate();
   }
   }
   public void onDraw(Canvas canvas)
  {
  if(undo)
  {
   paintForUndo.setStrokeWidth(12.0f);
  /*stroke width have to be set more than or equal to your painted 
  stroke width, if ignored border of the  painted region will be left   
   uncleared. */
  paintForUndo.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.CLEAR));
  drawOnCanvas.drawPath(unDonePath,paintForUndo);
  }
  }
HourGlass
  • 1,767
  • 1
  • 13
  • 28