Android 当我使其中一个布局无效时,为什么我的布局会完全重新绘制';你的看法如何?

Android 当我使其中一个布局无效时,为什么我的布局会完全重新绘制';你的看法如何?,android,android-layout,Android,Android Layout,我有一个复杂的框架布局,包含几个自定义视图。主视图是一个图形 覆盖图形的是一个自定义视图,它表示十字线指针,用户可以在图形周围拖动该指针来读取有关特定数据点的详细信息 框架布局捕获所有触摸事件,在其每个子视图上调用“点击测试”方法,以确定触摸是否在该视图上,然后将触摸事件发送到相应的视图 当用户触摸十字线并拖动它时,我将触摸事件传递给十字线,它使用该事件更新十字线的位置并使其失效 一切正常,除了 当我使这些子视图无效时,布局中的所有视图都将重新绘制。我知道这一点,因为我在开发者选项中打开了“显示

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

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

框架布局捕获所有触摸事件,在其每个子视图上调用“点击测试”方法,以确定触摸是否在该视图上,然后将触摸事件发送到相应的视图

当用户触摸十字线并拖动它时,我将触摸事件传递给十字线,它使用该事件更新十字线的位置并使其失效

一切正常,除了

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

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

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

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


关于可能发生的事情有什么线索吗?

视图无法绘制“仅仅是它自己”,因为它取决于它的父对象(它提供了通过
dispatchDraw
方法剪裁和翻译的
画布
)。失效要求整个视图树失效-这就是您要寻找的答案:)


如果您查看
ViewGroup
的源代码,您会发现有两种重要的方法:
dispatchDraw
(负责将draw事件下发到它的childs)和
drawChild
(由
dispatchDraw
调用,让您指定如何绘制childs)。请注意,虽然有指定无效区域的
RectF
,但没有检查哪个
View
开始无效。据我所知-您需要确保无效
视图
(十字)不会占据整个屏幕,因此重画将只是实际占据的部分。

如果您理解正确,十字线视图的线条会覆盖整个屏幕,即,一条从上到下的垂直线和一条从左到右的水平线

现在,如果您更改十字线的中心,而其他视图将不会被重新绘制,那么您的屏幕将很快被以前十字线位置的旧线条弄乱。您不希望这样,因此您可以很高兴其他视图也重新绘制了自己

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

尝试以下操作:

setDrawingCacheEnabled(true);
如果视图未更改,启用视图的图形缓存将使视图不会重新绘制


看一看:

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

this.invalidate()

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

你说
我怀疑我的代码是问题所在
,那么为什么不发布代码呢?@tolgap请查看我关于为什么不发布代码的评论。谢谢。啊,这完全有道理。我遇到的问题是,视图的大小必须与其父视图的大小相同,因为我绘制了一条水平线和垂直线,即它所覆盖的图形的宽度和高度。所以,如果我理解正确的话,除非我将十字分割成两个视图,并将它们的大小设置为线的厚度,然后用x和ys来定位它们,否则我无能为力。那样的话,只有RectF会因为重画而失效吗?我会玩一会儿(我想我现在明白原因了),几个小时后回来。谢谢@Simon别忘了图形缓存。重新绘制时,可能会绘制缓存以保留资源。所以,除非您有一些性能问题,否则不必担心整个视图树的重画。好的,很高兴知道。我实际上没有性能问题,我也没有做过早的优化——只是我注意到所有的东西都被重新绘制了,在我看来很难看。但是,你的洞察力帮了我很多。非常感谢。