1

I am trying to make undo,redo options in custom drawing view app. But it is not working as i want.

I am not good in english. Through picture, let me try to show the working of undo , redo functions. Hope so, this picture will explain my problem. enter image description here

i want to remove first line on first undo click and second line on second undo click and so on... similarly on redo click draw last line on first click, second last on second click and so on..

Here is my custom view class.

public class DrawingView extends View{

    ArrayList<Path> undoPath = new ArrayList<Path>();
    ArrayList<Path> paths    = new ArrayList<Path>();
    private static int pathSize =0;
    //draw path
    private Path drawPath;
    //drawing and canvas point
    private Paint drawPaint, canvasPaint;
    //initial color
    private int paintColor=0xFF660000;
    //canvas
    private Canvas drawCanvas;
    //canvas bitmap
    private Bitmap canvasBitmap;

    private float brushSize, lastBrushSize; 

    public DrawingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setupDrawing();
    }
    public void setPattern(String newPattern){
        invalidate();
        int patternID = getResources().getIdentifier(newPattern, "drawable", "com.faisalahsan.paintingapp");
        Bitmap patternBMP = BitmapFactory.decodeResource(getResources(), patternID);
        BitmapShader patternBMPShader = new BitmapShader(patternBMP, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        drawPaint.setColor(0xFFFFFFFF);
        drawPaint.setShader(patternBMPShader);

    }
    private void setupDrawing(){
        //get drawing area setup for interaction
        drawPath = new Path();
        drawPaint= new Paint();

        paths.add(drawPath);

        brushSize = getResources().getInteger(R.integer.medium_size);
        lastBrushSize = brushSize;

        drawPaint.setColor(paintColor);
        drawPaint.setAntiAlias(true);
        drawPaint.setStrokeWidth(brushSize);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);

        canvasPaint = new Paint(Paint.DITHER_FLAG);     
    }

    @Override
    protected void onDraw(Canvas canvas) {          
        for(Path p: paths){         
            canvas.drawBitmap(canvasBitmap, 0,  0, canvasPaint);
            canvas.drawPath(p, drawPaint);          
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {    
        super.onSizeChanged(w, h, oldw, oldh);
        canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);

    }

    public void onClickUndo () {
        if (paths.size()>0)  {
         undoPath.add(paths.remove(paths.size()-1));         
         invalidate();
        }          
       }

       public void onClickRedo (){
        if (undoPath.size()>0)  {
         paths.add(undoPath.remove(undoPath.size()-1));         
         invalidate();
         }
        }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float touchX = event.getX();
        float touchY = event.getY();

        switch (event.getAction()) {
        case  MotionEvent.ACTION_DOWN:
            drawPath.moveTo(touchX, touchY);
            break;          
        case MotionEvent.ACTION_MOVE:
            drawPath.lineTo(touchX, touchY);            
            break;
        case  MotionEvent.ACTION_UP:
            drawCanvas.drawPath(drawPath, drawPaint);
            drawPath.reset();
            drawPath = new Path();
            paths.add(drawPath);
            break;
        default:
            return false;
        }
        invalidate();
        return true;        
    }   
}
FAISAL
  • 459
  • 8
  • 22

1 Answers1

0

You are not "redrawing" on the canvas when "undo" removes the action from the ArrayList "paths" - in other words, taking it out of the list does not change the image. You have to redraw what was on the canvas before it was drawn in order to "undo" the action.

Save the state of the canvas when "onDraw" starts and then redraw that canvas when undo is called. You need to keep a synchronized stack of canvas states in order to perform a series of "undo" and "redo" calls.

Jim
  • 10,172
  • 1
  • 27
  • 36
  • can you please help me with some kind of example or piece of code?? – FAISAL Feb 10 '14 at 20:02
  • read up on this: http://stackoverflow.com/questions/3973557/how-to-implement-undo-redo-operation-without-major-changes-in-program?rq=1 you are missing the "stack" side (you are tracking "commands" but not the action stack... you will probably need a cached version of each Bitmap for memory reasons; so ArrayList bitmaps = new ArrayList(); where you store the state of them image before each change. But you will need caching for more than just a couple "undo" options. Then for "redo" you need another one like ArrayList redoBitmaps – Jim Feb 10 '14 at 23:45