【问题标题】:Android: invalidate(dirty)Android:无效(脏)
【发布时间】:2016-08-18 21:29:33
【问题描述】:

Android 似乎真的不喜欢 invalidate (Rect dirty),它只用于使画布的一部分无效。当我使画布的一部分无效(如下图绿色所示)并且需要同时重绘画布的 ToggleButton outside 时,红色显示的整个区域都会被擦除!似乎 Android 只是使包含需要重绘的两个区域的联合的最小矩形内的所有内容无效,即使其中一个区域位于我要使其无效的画布的 View 之外。

这是标准行为吗?如果是,为什么有人会使用部分失效?

【问题讨论】:

  • 如何阻止 android 擦除红色区域并仅重绘绿色区域,我在自己的实现中使用了 invalidate(rect) 但不知道如何在调用时在 onDraw() 中处理它从 invalidate() 到 onDraw()

标签: android android-canvas invalidation


【解决方案1】:

Android 有一个名为ViewRootImpl 的类。此类由您在屏幕上看到的每个窗口所拥有(术语窗口在这里有点混乱,因此对于这个解释,窗口是主要活动的布局,顶部没有任何对话框或弹出窗口)。 这个布局一直在被遍历,这意味着 Android 只是在等待这个窗口有一个脏矩形并绘制它。由于此窗口可能包含许多视图(按钮等),因此它会遍历所有视图并询问每个视图是否需要重绘。 每个视图都返回一个脏矩形给ViewRootImpl,所有这些矩形都连接到一个大矩形上,最后重新绘制。

为什么要这样做?好吧,ViewRootImpl 要求WindowManagerService 提供一个Canvas 以供使用。这意味着每次遍历时,一个窗口中的所有视图实际上共享一个Canvas

至于你的问题,如果只有一个特定的View 有一个脏矩形,那么只会绘制那个脏矩形,但由于另一个视图也有一个,所以脏矩形包含两者。

【讨论】:

    【解决方案2】:

    此问题是由硬件加速引起的。您必须在活动中禁用它才能使用invalidate(dirty rect)。要在您的活动中禁用硬件加速,请打开清单文件并添加:

    android:hardwareAccelerated="false"
    

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

    【讨论】:

    • 感谢您指出这一点!尽管我认为知道这一点非常重要,但此功能的文档中并未提及这一点。我花了半天时间调查为什么整个视图无效。
    • 此方法在 API 级别 28 中已弃用。developer.android.com/reference/android/view/…
    猜你喜欢
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多