android-discuss
android-discuss copied to clipboard
[问答] 打开硬件加速时,Canvas.getMatrix() 方法为什么也能返回正常的矩阵
在Canvas.getMatrix()
中有标记这个方法被废弃,因为:
Hardware accelerated canvases may have any matrix when passed to a View or Drawable, as it is implementation defined where in the hierarchy such canvases are created. It is recommended in such cases to either draw contents irrespective of the current matrix, or to track relevant transform state outside of the canvas.
(渣翻):在
Canvas
开启硬件加速后,getMatrix
获取到的矩阵可能完全不是你预期的样子,因为这个方法的具体实现被Canvas
创建的层级所决定,所以建议你要么不用获取到的matrix
做事情,要么在画布之外跟踪相关的变换状态
同时在这个Issue Tracker里,有开发者反馈:在开启硬件加速之后,做这样一个无害操作canvas.setMatrix(canvas.getMatrix())
居然会改变Canvas
的状态,也就是getMatrix()
和setMatrix()
不对应
谷歌员工对此的回复是:
When hardware acceleration is enabled, a View's drawing commands are recorded in a display list. At this point, a call to getMatrix() will only return the matrix built by the View itself. Any operation performed by the parents will not be taken into account (and cannot be taken into account, a display list can be generated before a View even have a parent.)
(渣翻):启用硬件加速后,View的绘图命令将被记录在
Display List
中。此时,getMatrix()
将仅返回由View本身构建的矩阵。父View执行的任何操作都不会被考虑在内(也没法考虑,因为Display List
在View拥有父View之前就已经生成了)
谷歌员工的解释补充了源码注释里一些晦涩的地方,整个机制看上去还是比较合理的,但我在进行验证的时候,却发现开启硬件加速后,无害操作canvas.setMatrix(canvas.getMatrix())
并没有改变Canvas
的状态(是在一个有状态栏标题栏的页面中,理论上父view对子view的canvas有平移操作),非常奇怪
而且运行Issue Tracker里开发者提供的代码,也能正常工作,没有出现该开发者描述的问题,如下图:
(运行环境为Android 8.0 虚拟机,并且能看到
canvas.isHardwareAccelerated
返回true也就是开启了硬件加速)
我终于在一个Android 6.0.1的手机上复现了这个现象,但是为什么都是开启硬件加速,大家的表现却不一样呢,是因为这取决于不同Android版本的具体实现吗?API上的废弃只是表明Android不保证它的实现,而不是说一定实现得跟关闭硬件加速不同?
如图: