安卓:使(dirty)失效

10
似乎Android非常不喜欢invalidate (Rect dirty),它用于仅使画布的一部分无效。当我使画布的一部分无效(如下图中绿色所示),同时需要重新绘制位于画布之外的一个ToggleButton时,整个红色区域都会被擦除!似乎Android只是使包围两个需要重新绘制的区域并集的最小矩形内的所有内容都无效,即使其中一个区域在我无效画布的视图之外。

这是否是标准行为?如果是,那么为什么要使用部分失效呢?

enter image description here


如何防止Android擦除红色区域并仅重新绘制绿色区域,我已在自己的实现中使用了invalidate(rect),但不知道在从invalidate()到onDraw()的调用中如何处理它。 - KingKongCoder
2个回答

16

Android有一个名为ViewRootImpl的类。每个屏幕上看到的窗口都拥有这个类(这里术语“窗口”有点困惑,因此在本说明中,窗口是指主活动的布局,没有任何对话框或弹出窗口在其上)。 该布局一直被遍历,这意味着Android只等待该窗口的脏矩形并进行绘制。由于此窗口可能包含许多视图(如按钮等),因此它会遍历所有这些视图,并询问每个视图是否需要重新绘制。 每个视图都会向ViewRootImpl返回一个脏矩形,所有这些矩形都加入到一个大矩形中,最后将其重新绘制。

为什么要这样做呢?嗯,ViewRootImpl会向WindowManagerService请求一个Canvas以进行绘制。这意味着,在遍历时,一个窗口中的所有视图实际上共享一个Canvas

至于您的问题,如果仅有一个特定的View具有脏矩形,则仅绘制该脏矩形,但由于另一个视图也具有脏矩形,则脏矩形包含两个矩形。


5

这个问题是由硬件加速引起的。为了使用invalidate(dirty rect),您必须在活动中禁用它。要在您的活动中禁用硬件加速,请打开清单文件并添加以下内容:

android:hardwareAccelerated="false"

现在您可以使用invalidate(dirty rect)


谢谢您指出这一点!尽管我认为这非常重要,但在该函数的文档中并没有提到。我花了半天时间调查为什么整个视图都无效了。 - Enemenemiste
此方法已在API级别28中被弃用。https://developer.android.com/reference/android/view/View#invalidate(android.graphics.Rect) - Anurag Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接