如何在我的绘图应用程序中实现撤消/重做

时间:2015-05-16 23:46:05

标签: java android eclipse draw undo-redo

我创建了一个应用程序来绘制并想要实现undo / redo的功能,我尝试了各种方法,但是没有一个工作,有人可以帮我吗?

这是我的代码:

变量

'public class MainDrawingView extends View {
public MainDrawingView(Context context, AttributeSet attrs) {

    super(context, attrs);
    setupDrawing();

}

float TOUCH_TOLERANCE = 4;
float mX, mY;
//drawing path
private Path drawPath, drawX, drawY;
//drawing and canvas paint
private Paint drawPaint;
private Paint canvasPaint;
private View canvasback;
private Paint bccanvas;
//initial color
private int paintColor = 0xFF000000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap, trans;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();'

SetupDrawing

'private void setupDrawing() {
    drawPath = new Path();
    drawPaint = new Paint();
    bccanvas = new Paint();
    drawPaint.setColor(paintColor);
    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(20);
    drawPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);
    canvasPaint = new Paint(Paint.DITHER_FLAG);

}'

onSizeChanged

'@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);

}'

触摸事件

'private void touch_start(float x, float y) {
    undonePaths.clear();
    drawPath.reset();
    drawPath.moveTo(x, y);

    mX = x;
    mY = y;
}

private void touch_move(float x, float y) {
    float dx, dy;
    dx = Math.abs(x - mX);
    dy = Math.abs(y - mY);
    if ((dx >= TOUCH_TOLERANCE) || (dy >= TOUCH_TOLERANCE)) {
        drawPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        drawPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        drawPath.lineTo(mX, mY);
        // commit the path to our offscreen
        drawCanvas.drawPath(drawPath, drawPaint);
        drawPath.reset();
        drawPath.moveTo(mX, mY);


        mX = x;
        mY = y;
    }
}

private void touch_up() {
    drawPath.reset();

}'

的onTouchEvent

'public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:

            touch_start(x, y);
            drawPath.moveTo(x, y);

            break;
        case MotionEvent.ACTION_MOVE:

            touch_move(x, y);
            drawPath.lineTo(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            drawPath.reset();
            touch_up();

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

的onDraw

'@SuppressLint("NewApi")
@Override
protected void onDraw(Canvas canvas) {

        canvas.drawPath(p, drawPaint);
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    }'

onClickUndo

'public void onClickUndo () {
        if (paths.size()>0){

        undonePaths.add(paths.remove(paths.size()-1));
        invalidate();
        undonePaths.clear();
    }
    else
    {

    }
    //toast the user
}'

onClickRedo

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

    }
    //toast the user
}'

2 个答案:

答案 0 :(得分:0)

TL; DR

几个月前我在Java Swing中创建了一个类似的应用程序。我实现这两种方法的方式是我创建了一个堆栈形状,当用户向白板添加形状然后从此推送/弹出以撤消/重做时(存储在临时变量中删除的形状) )

protected Shape removed; //shape object of an undo-ed object
protected Stack<Shape> shapes = new Stack<Shape>(); //stack to store the shapes

public void undo() 
{
    if (!shapes.empty()) //only undo if there's shapes on the board
    {
        removed = shapes.pop(); //pop removes a shape and returns it into 'removed' object
        repaint();
    }
}

public void redo() 
{
    if (removed != null)  //only redo if something has been undone
    {
        shapes.push(removed); //push adds the object back onto the stack
        removed = null;
        repaint();
    }
}

我希望这有帮助!

答案 1 :(得分:0)

一个好的方法是创建一个名为“Undoable”的界面。它至少有3个覆盖:do(),undo()和redo()。然后在实现Undoable的类中完成所有工作,并保留一堆这些=撤消历史记录。