Answers:
为了更好地理解FrançoisBOURLIEUX和Dalvik提供的答案,我建议您看一下Arpit Mathur的这张令人敬畏的视图生命周期图:
TextView
。我想,也许他们想得出View
最后一次他们改变其布局相关参数之前,但它并没有真正使任何意义,如果我们想在不同的顺序被调用这些电话(他们称之为invalidate()
后立即requestLayout()
在TextView
以及)。也许值得在StackOverflow上提出另一个问题:)?
invalidate()
和requestLayout()
)。这些方法的目的是告诉您发生了View
什么样的失效(如您所说的)。View
调用这些方法之一后,并不能决定要遵循的路径。选择View
-lifecycle-path 的逻辑是选择适当的方法来调用自身。如果存在与尺寸更改有关的某些内容- requestLayout()
应该调用,如果只有视觉更改而尺寸没有更改-您应该调用invalidate()
。
View
以某种方式更改大小,例如,获得a的当前LayoutParams
值View
并对其进行修改,但不调用requestLayout
或setLayoutParams
(requestLayout
内部调用),则可以随意调用invalidate()
,并且该View
不会通过测量布局过程中,因此不会改变它的大小。如果您不告诉您View
它的大小已更改(使用requestLayout
方法调用),则View
will将假定它没有更改,并且onMeasure
and onLayout
将不会被调用。
invalidate()
invalidate()
当您要计划重绘视图时,调用完成。它将导致onDraw
最终被调用(很快,但不是立即)。自定义视图何时调用的示例是文本或背景颜色属性已更改。
视图将被重绘,但大小不会改变。
requestLayout()
如果关于视图的某些更改会影响大小,则应致电requestLayout()
。这将触发onMeasure
和onLayout
不仅是这个观点,但一路上扬父视图的线。
不能保证调用requestLayout()
会导致onDraw
(与接受的答案中的图相反),因此通常将其与结合使用invalidate()
。
invalidate();
requestLayout();
例如,自定义标签的text属性发生更改时。标签会改变尺寸,因此需要重新测量和重新绘制。
forceLayout()
在requestLayout()
父视图组上调用时,不需要重新测量并重传其子视图。但是,如果在重新测量和重排中应包括一个孩子,则可以呼叫forceLayout()
该孩子。forceLayout()
仅在子代requestLayout()
与其直接父代一起出现时才对子代起作用。forceLayout()
本身调用不会产生任何效果,因为它不会触发requestLayout()
视图树。
阅读此问答以获取有关以下内容的详细说明forceLayout()
。
View
源代码requestLayout()
在invalidate()
需要时致电。没有人做布局或立即绘制。相反,它们设置标志,最终将导致重新布局并重画。
在这里您可以找到一些响应:http : //developer.android.com/guide/topics/ui/how-android-draws.html
对我来说,invalidate()
仅调用会刷新视图,而调用会requestLayout()
刷新视图并计算屏幕上视图的大小。
这个答案是不正确的forceLayout()
。
如您在代码中所见forceLayout()
它仅将视图标记为“需要重新布局”,但是它既不计划也不触发该重新布局。重新布局将不会发生,直到将来某个时候由于其他原因布置视图的父级。
使用forceLayout()
和时,还有一个更大的问题requestLayout()
:
假设您已经调用forceLayout()
了一个视图。现在,当调用requestLayout()
该视图的后代时,Android将递归调用requestLayout()
该后代的祖先。问题在于它将在您调用的视图处停止递归forceLayout()
。因此,该requestLayout()
调用将永远不会到达视图根,因此也不会调度布局遍历。视图层次结构的整个子树都在等待布局,并且调用requestLayout()
该子树的任何视图都不会导致布局。仅requestLayout()
在该子树之外调用任何视图都会破坏该咒语。
我会考虑的实现forceLayout()
(以及它如何requestLayout()
被破坏,因此您永远不要在代码中使用该函数。
View
并亲自遇到问题并对其进行调试来解决了。
forceLayout()
API 的用途感到好奇:它实际上并没有强制执行布局传递,而只是更改了在中观察到onMeasure()
的标志,但是onMeasure()
除非被调用requestLayout()
或显式调用,否则它不会被View#measure()
调用。也就是说,forceLayout()
应该与配对requestLayout()
。另一方面,forceLayout()
如果仍然需要执行,为什么还要执行requestLayout()
呢?
requestLayout()
做所有forceLayout()
也做的事情。
forceLayout
有道理的。因此,最后它的命名和记录都非常糟糕。
invalidate()
---> onDraw()
来自UI线程
postInvalidate()
---> onDraw()
来自后台线程
requestLayout()
---> onMeasure()
和onLayout()
AND 不一定 onDraw()
forceLayout()
---> onMeasure()
和onLayout()
JUST如果直接父级调用requestLayout()
。