背景
我正在开发一个包含大量 Canvas 绘图而不是多个 View 的库(可用 here )。
问题
当我努力改进它并使其满足我们对应用程序的需求(需要一些定制)时,我注意到有一些行被标记为已弃用:
canvas.clipRect(0f, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, height.toFloat(), Region.Op.REPLACE)
问题是,我认为没有合适的人选来用较新的 API 替换这行代码
我发现了什么
查看the docs ,这是写的:
This method was deprecated in API level 26. Region.Op values other than INTERSECT and DIFFERENCE have the ability to expand the clip. The canvas clipping APIs are intended to only expand the clip as a result of a restore operation. This enables a view parent to clip a canvas to clearly define the maximal drawing area of its children. The recommended alternative calls are clipRect(RectF) and clipOutRect(RectF);
所以我尝试使用这两个函数中的任何一个,但它们都导致了与过去一样的绘图问题。
看deprecation,好像是函数本身被标记了,而不是Region.Op.REPLACE :
所以也许它真的没有其他选择...
问题
- 在这种情况下最好的选择是什么?
- 为什么它被弃用了?
- 与一些已弃用的函数相反,我认为这个函数应该可以安全地继续使用,以防我找不到替代品,对吧?
最佳答案
1:所有使用自定义的方法Region.Op
现在已弃用,因此现在只能使用两种方法变体:clipRect
/clipPath
(代表 Region.Op.INTERSECT
)和 clipOutRect
/clipOutPath
(代表 Region.Op.DIFFERENCE
)。实现类似Region.Op.REPLACE
的功能必须使用 save()
和 restore()
方法。
所以以前(使用 Op.REPLACE)你只会调用:
canvas.clipRect(0, 0, 100, 100); // do some clipping
canvas.drawLine(...); // do some clipped drawing
canvas.clipRect(200, 200, 400, 400, Region.Op.REPLACE); // replace clipping region to completely different one
canvas.drawLine(...); // and some other drawing
但现在您必须手动保存和恢复以前的 Canvas 状态:
canvas.save(); // IMPORTANT: save current state of clip and matrix (i.e. unclipped state) (let's say it's state #1)
canvas.clipRect(0, 0, 100, 100); // do some clipping
canvas.drawLine(...); // do some clipped drawing
canvas.restore(); // IMPORTANT: get back to previously saved (unclipped) state of the canvas (restores state #1)
canvas.save(); // now save again the current state of canvas (clip and matrix) (it's state #2)
canvas.clipRect(200, 200, 400, 400); // now we can do some other clipping (as we would do with Region.Op.REPLACE before)
canvas.drawLine(...); // and some other drawing
canvas.restore(); // get back go previously saved state (to state #2)
注意 Canvas 内部使用栈,所以你甚至可以调用 save()
在不同的时刻多次。你不能调用canvas.restore()
比 canvas.save()
次数多被称为。
同样重要的是,调用 canvas.restore()
更改剪辑矩形(与调用 canvas.save()
时的值相同)。所以你必须小心放置 restore()
在需要应用裁剪的所有绘图方法之后调用。
2:可能是因为一些性能优化。我想我在某处读到(我现在找不到),对于 GPU 上的硬件加速,他们只能使用 INTERSECT/DIFFERENCE 剪辑操作,而其他操作必须回退到 CPU 处理。这可能是原因。
编辑:Here是一些相关的答案,因为 ICS 启用了硬件加速,所以不支持某些 ClipRect 操作。
3:正如他们在文档中所说,它将在 Android P 中停止工作(可能仅在针对 Android P 时):
As of API Level API level Build.VERSION_CODES.P only INTERSECT and DIFFERENCE are valid Region.Op parameters.
关于android - `canvas.clipRect` 和 `Region.Op.REPLACE` 的最佳替代方案是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50231950/