Функциональность Undo Redo не работает.

Я работаю над приложением для рисования для пользователей Android. Я хочу реализовать функцию отмены повтора в моем приложении. Я направляю вопросы, размещенные в stackru, для решения моей проблемы, но я не смог найти правильное решение для своего кода. Ниже я публикую свой код, пожалуйста, помогите мне избавиться от этой проблемы. Любая помощь будет высоко оценена.

Заранее спасибо.

public class DrawingView extends View {

 private ArrayList<Path> paths = new ArrayList<Path>();
 private ArrayList<Path> undonePaths = new ArrayList<Path>(); 

public DrawingView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
    this.context = context;
    setupDrawing();
}

public void setupDrawing(){

    drawPath = new Path();
    drawPaint = new Paint();

    canvasPaint = new Paint(Paint.DITHER_FLAG);

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

    paths.add(drawPath);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
    super.onSizeChanged(w, h, oldw, oldh);

    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

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

@Override
public boolean onTouchEvent(MotionEvent event) {

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

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


public void onClickUndo(){
    if(paths.size()>0){
        undonePaths.add(paths.remove(paths.size() - 1));
        Toast.makeText(getContext(), "Undo is working", Toast.LENGTH_LONG).show();
        invalidate();
    }
    else{
        Toast.makeText(getContext(), "Undo is not working", Toast.LENGTH_LONG).show();
    }
}

public void onClickRedo(){
    if(undonePaths.size()>0){
        paths.add(undonePaths.remove(undonePaths.size() - 1));
        Toast.makeText(getContext(), "Redo is working", Toast.LENGTH_LONG).show();
        invalidate();
    }
    else{
        Toast.makeText(getContext(), "Redo is not working", Toast.LENGTH_LONG).show();
    }
}

}

2 ответа

Всего несколько небольших изменений.

Там дополнительный Path в ваших списках это приведет к тому, что шаг Undo/Redo практически ничего не сделает, когда все остальное будет исправлено. Так в setupDrawing() Удалить:

paths.add(drawPath);

в onDraw() метод, удалить:

canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);

это drawBitmap() вызов перерисовывал элемент Bitmap, к которому обращается каждый ACTION_UP, делая это, как будто ваш Path списки не обновлялись.

Затем в onTouchEvent() метод, в MotionEvent.ACTION_DOWN ун-комментарий:

undonePaths.clear();

и изменить MotionEvent.ACTION_UP дело в:

case MotionEvent.ACTION_UP:
    drawCanvas.drawPath(drawPath, drawPaint);
    paths.add(drawPath);  
    drawPath = new Path();
    break;

reset() звонок очищал Pathкоторый ты не хочешь. Вместо этого, здесь мы добавляем недавно завершенный Path в список, а затем создайте новый, чтобы продолжить.

NB. То, как это работает в настоящее время, функциональность Undo/Redo не повлияет на canvasBitmap, Поскольку неясно, для чего предназначен этот Bitmap, я оставил его как есть. Если вы хотите, чтобы это растровое изображение отражало представления, вы можете просто переместить drawCanvas.drawPath() звонки в onDraw()параллельно с canvas.drawPath() звонит туда.

var undoRedo = new Array();
var unStep = -1;

function historySave() {
    unStep++;
    while (undoRedo.length > 20) {
        undoRedo.shift();
        unStep--;
    }
    if (unStep !== 0 && unStep < undoRedo.length) {
        undoRedo.length = unStep;
        unStep++;
    } else {
        undoRedo.length = unStep;
    }
    undoRedo.push(document.getElementById('drawingCanvas').toDataURL());    
}

function Undo() {
    if (unStep > -1) {
        unStep--;
        var canvasPic = new Image();
        canvasPic.src = undoRedo[unStep];
        drawingContext.clearRect(0,0,drawingCanvas.width,drawingCanvas.height);
        canvasPic.onload = function () {
        drawingContext.drawImage(canvasPic, 0, 0);
            }
    }
}

function Redo() {
    if (unStep < undoRedo.length - 1) {
        unStep++;
        var canvasPic = new Image();
        canvasPic.src = undoRedo[unStep];
        canvasPic.onload = function ()  { 
        drawingContext.drawImage(canvasPic, 0, 0);
        }
    }
} 
Другие вопросы по тегам