android - `canvas.clipRect` 和 `Region.Op.REPLACE` 的最佳替代方案是什么?

标签 android canvas

背景

我正在开发一个包含大量 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 :

enter image description here

所以也许它真的没有其他选择...

问题

  1. 在这种情况下最好的选择是什么?
  2. 为什么它被弃用了?
  3. 与一些已弃用的函数相反,我认为这个函数应该可以安全地继续使用,以防我找不到替代品,对吧?

最佳答案

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/

相关文章:

android - Bundle.putExtra 问题与 android

android - 点击通知应用程序后未在 android 12 版本中启动?

asp.net - $.ajaxFileUpload 与 Canvas 一起使用

javascript - 如何使用 JavaScript 截取 Google Maps 的部分内容

android - Google Places API Picker 仅显示特定类型的地点

android - 在 Android ADT Eclipse 插件中滚动布局编辑器

java - 调用 .text() 方法时 Jsoup 元素不显示

html - 固定位置的菜单栏与 Canvas 重叠

javascript - 如何使用更好的插值在 html5 Canvas 上缩放图像?

javascript - 使用 Canvas 上下文作为全局工作,但当我传递它时却不起作用