【问题标题】:Remove a drawn line from canvas从画布上删除画线
【发布时间】:2016-07-05 13:07:25
【问题描述】:

我已经完成了通过手指在画布上画线的代码并且也实现了 “撤消”类型的功能。撤消对于不相互交叉的线非常有效,但是当线相互交叉并且我撤消上一行时,它也会在“交叉”点影响另一条线,请查看图片

我用这个代码作图

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(16);
mPaint.setXfermode(null);

//In MotionEvent.ACTION_DOWN:
mPath.reset();
mPath.moveTo(x, y);

// In MotionEvent.ACTION_MOVE:
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);

// In MotionEvent.ACTION_UP:
mPath.lineTo(mX, mY);
circlePath.reset();
mCanvas.drawPath(mPath, mPaint);
mPath.reset();

Now from ACTION_DOWN to ACTION_UP i keep track of all the x,y coordinates to use them for undo feature & here's how i Undo

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(20);

// This helps to have undo kind of effect
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

ACTION_UP, ACTION_DOWN & ACTION_MOVE 的其余代码相同。所以基本上 我只是用

在相同的 x-y 坐标上画另一条线
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

& 结果与图中红色圆圈标记的结果相同。

那么,即使它们具有相同的 xy 坐标,我如何才能只擦除特定线的一部分,我可以在绘制后将绘制的线转换为 ImageView / Bitmap 以便我可以删除 ImageView它自己和它不影响另一条线? 或者有没有更好的方法来实现这一点?

【问题讨论】:

    标签: android android-canvas


    【解决方案1】:

    您无法撤消 Canvas 上的绘图。来自documentation

    通过画布,您的绘图实际上是在底层执行的 位图,放置在窗口中。

    解决问题的一种方法是使用备份Bitmap 来保存当前Bitmap 的状态,然后再使用它,例如使用Memento pattern

    看看Fast undo/redo for bitmap editor when memory is limited?Fast undo facility for bitmap editor application(最后一个针对iPhone,但基本思路是一样的)

    另一种减少内存消耗的方法是保存您想要在画布上绘制的对象的状态并按需绘制它们。

    【讨论】:

    • 意味着在绘制一条线后,我需要在 ACTION_DOWN 发生之前存储位图,并且在撤消时,我应该再次将该位图设置为整个视图或其他什么?
    • 是的,您需要以某种方式存储之前的状态。在每个动作之前存储Bitmap 可能会非常消耗内存,也许最好存储事件的状态并按需重绘Bitmap
    • 抱歉,我不确定“存储事件的状态”,您能简单地说一下吗?
    • 想象一下你想画一堆由用户画的线,你希望能够分别撤消每条线。您可以使用结构存储线条,并将线条从结构中绘制到位图中。当用户撤消时,您从结构中删除您的线条并完全重绘位图(清理它并再次从结构中重绘所有线条)。要保持结构的不同状态,您可以使用 Memento 模式
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 2012-07-19
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多