4

我有一个复杂的框架布局,其中包含几个自定义视图。主视图是一个图表。

覆盖图形的是一个自定义视图,它表示一个十字形指针,用户可以在图形周围拖动它以读取有关特定数据点的详细信息。

框架布局捕获所有触摸事件,在它的每个子视图上调用“命中测试”方法以确定触摸是否在该视图上,然后将触摸事件分派到适当的视图。

当用户触摸十字准线并拖动它时,我将触摸事件传递给十字准线,它用于更新其位置并使自身无效。

一切正常,除了...

当我使这些子视图中的任何一个无效时,布局中的所有视图都在重绘。我知道这一点,因为我在开发人员选项中打开了“显示屏幕更新”。在任何时候我都不会使包含的 FrameLayout 无效 - 或者至少在不知情的情况下。

当然,处理布局的 Activity 不会使其无效,并且我在子视图中没有对父级的任何引用。

我没有发布代码,因为 a) 我不知道这是否是正常行为,b) 有很多!c) 如果这不是正常行为,我不知道代码的哪一部分有问题。当然,我很乐意提供任何可能被要求的东西。

我的最低 API 是 2.3.3,我的目标是 4.0。这两个版本都发生了这种情况,所以我怀疑我的代码是问题所在,但从哪里开始呢?

关于可能发生的事情的任何线索?

4

4 回答 4

6

没有办法View绘制“只是它自己”,因为它取决于它的父级(它提供了Canvas通过dispatchDraw方法对其进行剪辑和翻译)。失效需要使整个视图树失效-这是您正在寻找的答案:)

如果您查看 的来源ViewGroup,您会发现有两个重要的方法:(dispatchDraw负责将绘图事件分派给它的孩子)和drawChild(由它调用dispatchDraw,让您指定如何绘制孩子)。请注意,没有检查从哪个View开始失效,尽管有一个RectF指定失效区域。据我了解 - 您需要确保您的无效View(交叉)不会占用整个屏幕,因此重绘将只是它实际占用的那部分。

于 2013-07-06T11:16:29.657 回答
2

如果你没听错的话,十字线视图的线条覆盖了整个屏幕,即从上到下一根垂直线,从左到右一根水平线。

现在,如果您更改十字准线的中心并且不会重绘其他视图,您的屏幕很快就会被先前十字准线位置的旧线弄乱。你不会想要这个,所以你可以很高兴其他视图也重新绘制自己。

如果需要,您可以指定一个“脏”矩形并调用invalidate(Rect dirty),这不会重绘完全在该矩形之外的视图。尽管在这种情况下由您决定,但不要更改该矩形之外的任何内容。

于 2013-07-06T12:41:45.423 回答
0

尝试这个:

setDrawingCacheEnabled(true);

如果视图未更改,启用视图的绘图缓存将不会重绘视图

看一看: Android Invalidate() only single view

于 2015-06-17T08:49:08.613 回答
0

可能是我的答案很简单,但我在帮助下解决了这个问题:

this.invalidate()

为每个画布视图运行它,它将一个一个更新(不是一次全部更新)

于 2019-08-08T09:32:39.707 回答