So I would like to implement an undo button for a drawing app I am working on for android. My current idea is to put the current draw path into a list of paths on MotionEvent.ACTION_UP. In onDraw(), simply draw everything that is in the list of paths. When the user presses undo, you remove the last drawn path from the list of paths and call invalidate(), forcing onDraw() to be called, which will draw everything in the list of paths. Since we removed the previous path from the list, that path should not be drawn and therefore should be "undone".
The problem I am having is the path never seems to actually be undone. It seems like the logic in my head is correct, but this implementation does not work correctly. Any help will be greatly appreciated.
Here is my code:
DrawingView.java:
Instance variables (to clarify following methods):
private Context context;
private Path drawPath;
private Paint drawPaint;
private Paint canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private int previousPaintColor;
private int paintColor;
private float brushSize;
private float eraserSize;
private float lastBrushSize;
private boolean isErasing = false;
private List<Path> moveList = null;
private List<Path> undoList = null;
private List<Path> currentMoveList = null;
Called from constructor:
private void setupDrawing() {
drawPath = new Path();
drawPaint = new Paint();
brushSize = getResources().getInteger(R.integer.default_brush_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);
}
onDraw:
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
for (Path path : currentMoveList) {
canvas.drawPath(path, drawPaint);
}
for (Path path : moveList) {
canvas.drawPath(path, drawPaint);
}
}
onTouchEvent:
@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);
currentMoveList.add(drawPath);
break;
case MotionEvent.ACTION_UP:
drawPath.lineTo(touchX, touchY);
drawCanvas.drawPath(drawPath, drawPaint);
moveList.add(drawPath);
drawPath = new Path();
currentMoveList.clear();
break;
default:
return false;
}
invalidate();
return true;
}
undo() :
public void undo() {
if (moveList.size() > 0) {
undoList.add(moveList.remove(moveList.size() - 1));
invalidate();
}
}
Regards,
Kyle.
After some trial and error, here is the fix:
Remove this line of code:
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
from onDraw() method and everything works perfectly :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With