`canvas.clipRect`与`Region.Op.REPLACE`的最佳替代方法是什么?

and*_*per 14 android canvas

背景

我正在开发一个有很多画布而不是多个视图的库(可在这里找到).

问题

当我努力改进它并使其适合我们对应用程序的需求(需要一些自定义)时,我注意到有一些行被标记为已弃用:

canvas.clipRect(0f, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, height.toFloat(), Region.Op.REPLACE)
Run Code Online (Sandbox Code Playgroud)

事实上,我不认为有一个很好的候选人用新的API替换这行代码

我发现了什么

看看文档,这是写的:

此方法在API级别26中已弃用.Interface.Op除INTERSECT和DIFFERENCE之外的值可以展开剪辑.画布剪辑API仅用于作为还原操作的结果展开剪辑.这使视图父级能够剪切画布以清楚地定义其子画面的最大绘制区域.推荐的替代调用是clipRect(RectF)和clipOutRect(RectF);

所以我尝试使用这些功能中的任何一个,但是它们都引起了以前的绘制问题.

看看弃用,似乎标记了函数本身,而不是Region.Op.REPLACE:

在此输入图像描述

所以也许它真的没有替代品......

问题

  1. 在这种情况下,最好的选择是什么?
  2. 为什么要弃用?
  3. 与一些不赞成使用的函数相反,我认为如果我找不到替代函数,这个函数应该是安全的,对吧?

Rob*_*yer 33

1:Region.Op现在不推荐使用自定义的所有方法,因此现在只能使用两种方法变体:clipRect/ clipPath(代表Region.Op.INTERSECT)和clipOutRect/ clipOutPath(代表Region.Op.DIFFERENCE).要实现类似于Region.Op.REPLACE一个必须使用save()restore()方法的功能:

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
Run Code Online (Sandbox Code Playgroud)

注意Canvas内部使用堆栈,因此您甚至可以save()在不同时刻多次调用.你不能打电话canvas.restore()多次canvas.save().

同样重要的是要求调用canvas.restore()更改剪辑rect(与canvas.save()调用时的值相同).因此,您必须restore()在需要应用剪切的所有绘图方法之后仔细调用调用.

2:可能是因为一些性能优化.我想我读到了某个地方(我现在找不到),对于GPU上的硬件加速,他们只能使用INTERSECT/DIFFERENCE剪辑操作,其他必须回退到CPU处理.这可能就是原因.

编辑:是一些相关的答案,由于ICS启用了硬件加速,因此不支持某些ClipRect操作.

3:正如他们在文档中所说,它将停止在Android P中工作(可能仅在定位Android P时):

从API Level API级别Build.VERSION_CODES.P开始,只有INTERSECT和DIFFERENCE是有效的Region.Op参数.

  • 这是我编辑过的文件,我还没有测试过,但这是它的工作方式.看看我在canvas.save()和canvas.restore()中添加了哪些行.https://gist.github.com/Robyer/17fa5d479c49497d369dda2678578012 (5认同)
  • 我很高兴它奏效了.问题是,真正的解决方案并不简单,只需将一行(原始的clipRect与Op.Replace)更改为另外两行(保存/恢复),但您必须了解正在进行的操作.调用clipRect()会影响之后调用的所有绘图方法,因此必须将保存/恢复调用放在正确的位置.重要的一点是,restore()调用将clipRect更改为原始值(调用save()时的值).这可能就是你遇到问题的原因.我也更新了答案(+可能的表现原因). (3认同)
  • @JoyRex我的整个答案和所有评论都在处理不推荐使用的clipRect方法。你看过吗?都在那里;) (2认同)