视图的高效“截图”?

时间:2013-03-21 15:04:30

标签: android

TL; DR:由于getDrawingCache()似乎在启用硬件加速时触发了View的完全重绘,是否有另一种方法可以获得Bitmap(或者其他内容)避免这种情况,可能是在最后一次绘制View时读取填充到(硬件,软件)层的数据?


一些背景知识:

Android已经能够自Android 3.0以来镜像屏幕,例如连接到HDMI显示器。这可以用于演示,但这意味着观众看到与演示者相同的东西,这并不总是理想的。

Android 4.2添加了Presentation,允许应用在“第二屏幕”上放置任意内容(例如,HDMI附加显示)。在这种情况下,有时第二个屏幕显示主平板电脑显示屏上的内容 part 会很有用。如果您想到Microsoft PowerPoint,LibreOffice Impress等演示软件,在典型的双屏幕设置中,观众会看到当前的演示幻灯片,而演示者会看到当前的幻灯片以及计时器和演讲者注释...... / p>

对于非交互式内容,例如代表幻灯片的PNG,这只是在两个屏幕上显示相同图像的问题(以及主屏幕上的其他内容)。

但是,对于交互式内容,例如WebView,有时很难进行此类镜像。例如,我们没有好的方法可以知道WebView的内容何时可能会发生变化,因为它可能基于纯粹在WebView内部的内容(例如,完成AJAX调用)而不是我们分开做的事情。而且,即使我们 知道WebView的内容何时发生了变化,我们也没有办法让其他WebView呈现相同的内容。

所以我想我会尝试设置一个MirroringFrameLayout,使用getDrawingCache()来检索容器内容的Bitmap并将其传递给可以在其上呈现的人 - 屏幕(例如,ImageView中显示的Presentation

但是,启用硬件加速后,setDrawingCacheEnabled(true) is somewhat of a no-op

  

启用绘图缓存类似于关闭硬件加速时设置图层。打开硬件加速时,启用绘图缓存对渲染没有影响,因为系统使用不同的加速机制忽略该标志。

在这些情况下调用getDrawingCache()会强制draw() View到位图支持的Canvas,而不是实际使用缓存。由于draw()可能会很昂贵,因此频繁执行draw()(例如,通过postOnAnimation()触发)会导致jank。

因此,我试图确定是否还有其他“绘图缓存”,超出getDrawingCache(),我们可以在启用硬件加速时使用,可用于设置此镜像,这是更多高效。从我所看到的,没有这样的缓存,因为从SDK应用程序的角度来看,层是有效的只写。但是,我希望也许我错过了一些解决方案。

提前致谢!

1 个答案:

答案 0 :(得分:13)

您可以使用setLayerType(View.LAYER_TYPE_SOFTWARE, null),但它会产生副作用,即每次更新时都会使View重绘速度较慢。创建一个在两个画布上绘制视图的自定义ViewGroup会更高效(每个屏幕一个)。您也可以简单地使用ViewTreeObserver并在每个绘制回调上强制您的视图渲染在第二个屏幕上。我真的建议你不要试图滥用这种用例的绘图缓存/图层类型。