使用Canvas在Android绘图应用程序中撤消和重做功能

时间:2016-08-01 13:46:08

标签: java android canvas

我正在开发一个我创建绘图镜像的项目。我的主要逻辑工作正常。导致问题的唯一原因是重做和撤消功能。 我搜索了很多。实施可能的方法,但无法取得成功。以下是我的绘图课程。

DrawingView.java

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

public DrawingView(Context context, AttributeSet attrs){
    super(context, attrs);
    this.context=context;
    setupDrawing();


}

//setup drawing
private void setupDrawing(){

    //prepare for drawing and setup paint stroke properties
    brushSize = getResources().getInteger(R.integer.small_size);
    lastBrushSize = brushSize;
    drawPath = new Path();
    drawPath1 = new Path();
    drawPaint = new Paint();
    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);
}

//size assigned to view
@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);
    width=w;
    height=h;
    Log.d("width,height", w + " , " + h);
    drawCanvas = new Canvas(canvasBitmap);




}

//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {

    for (Path p : paths){canvas.drawPath(p, drawPaint);}
    canvas.drawPath(drawPath, drawPaint);
    Log.i("OnDRAWING", "REACH ON DRAW");
    /*canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    canvas.drawPath(drawPath, drawPaint);
    canvas.drawPath(drawPath1, drawPaint);*/






}

//register user touches as drawing action
@Override
public boolean onTouchEvent(MotionEvent event) {



    float touchX = event.getX();
    float touchY = event.getY();
    //respond to down, move and up events
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        drawPath.reset();
        undonePaths.clear();
        drawPath.moveTo(touchX, touchY);
        undonePaths.clear();



        break;
    case MotionEvent.ACTION_MOVE:
        drawPath.lineTo(touchX, touchY);


        break;
    case MotionEvent.ACTION_UP:
        drawPath.lineTo(touchX, touchY);
        drawCanvas.drawPath(drawPath, drawPaint);// commit the path to our offscreen
        paths.add(drawPath);
        drawCanvas.drawPath(drawPath, drawPaint);
        drawPath.reset();

        drawCanvas.drawPath(drawPath1, drawPaint);
        drawPath1.reset();

        break;
    default:
        return false;
    }
    //redraw
    invalidate();
    return true;

}

我在这里缺少什么? 任何建议/想法/例子是在我的项目中实现这种功能的最佳方式吗?

1 个答案:

答案 0 :(得分:1)

画布绘制是一种层次结构,因为绘图按照您执行的顺序进行。

因此,所有绘图都应该在onDraw中完成,并且只在此处完成。

您的绘制事件应该在绘制堆栈上推送。您不存储画布。您只需存储最终发生绘图时应该发生的操作(例如路径的坐标,宽度和颜色)。

&#34;撤消&#34;操作可以通过从绘图堆栈弹出并将事件推送到&#34; redo&#34;堆。 &#34;重做&#34;事件可以通过弹出&#34;重做&#34;堆叠并推回到&#34;绘图&#34;堆。

在View的onDraw方法中,只需扫描绘图事件并在画布上绘图。

编辑:

onDraw()方法只会遍历绘图操作。首先,您可以像interface那样调用DrawEvent

public interface DrawEvent {
   void draw(Canvas c);
}

然后在您的View类中收集DrawEvents的集合,并在onDraw(Canvas c)中迭代它们。

public class MyView extends View {
    Deque<DrawEvent> drawEvents = new LinkedList<DrawEvent>();

    @Override
    public void onDraw(Canvas c) {
       for (DrawEvent e : drawEvents) {
           e.draw(c);
       }
    }
}