我对forceLayout()
类的requestLayout()
,invalidate()
和View
方法的作用感到有点困惑。
他们何时被召唤?
答案 0 :(得分:309)
为了更好地理解François BOURLIEUX和Dalvik提供的答案,我建议您按Arpit Mathur查看这个令人敬畏的视图生命周期图:
答案 1 :(得分:97)
invalidate()
如果要安排重绘视图,则会调用invalidate()
。这将导致onDraw
最终被调用(很快,但不是立即)。自定义视图调用它的示例是文本或背景颜色属性发生更改时。
视图将被重绘,但大小不会改变。
requestLayout()
如果您的观看内容发生变化会影响尺寸,则应致电requestLayout()
。这将不仅会触发此视图的onMeasure
和onLayout
,还会触发父视图的整个行。
调用requestLayout()
为not guaranteed to result in an onDraw
(与接受的答案中的图表相反),因此通常与invalidate()
结合使用。
invalidate();
requestLayout();
此示例是自定义标签的文本属性已更改。标签会改变尺寸,因此需要重新测量和重新绘制。
forceLayout()
如果在父视图组上调用requestLayout()
,则无需重新测量并重新布局其子视图。但是,如果孩子应该被包括在重新测量和重新布局中,那么您可以给孩子打电话forceLayout()
。 forceLayout()
仅适用于与其直接父级requestLayout()
一起发生的子项。单独调用forceLayout()
将不起作用,因为它不会触发视图树requestLayout()
。
阅读this Q&A,了解forceLayout()
的详细说明。
答案 2 :(得分:25)
在这里您可以找到一些回复: http://developer.android.com/guide/topics/ui/how-android-draws.html
对我来说,对invalidate()
的调用只会刷新视图,并且对requestLayout()
的调用会刷新视图并计算屏幕上视图的大小。
答案 3 :(得分:3)
您在要重绘的视图上使用invalidate(),它将调用onDraw(Canvas c),而requestLayout()将使整个布局渲染(测量阶段和定位阶段)再次运行。如果要在运行时更改子视图的大小,则应该使用它,但仅在特殊情况下(如父视图中的约束)(我的意思是父高度或宽度为WRAP_CONTENT,因此匹配测量子项,然后再将它们包装起来)
答案 4 :(得分:3)
forceLayout()
,This answer不正确。
正如您在the code of forceLayout()
中所看到的那样,它只是将视图标记为"需要重新布局"但它既不安排也不触发重新布局。重播将不会发生,直到将来某个时候,观点的父母出于其他原因进行了布局。
使用forceLayout()
和requestLayout()
时,还有一个更大的问题:
我们假设您已在视图中调用forceLayout()
。现在,当在该视图的后代上调用requestLayout()
时,Android将递归调用该后代的祖先上的requestLayout()
。问题是它会在你称之为forceLayout()
的视图上停止递归。 因此requestLayout()
调用永远不会到达视图根目录,因此从不安排布局传递。视图层次结构的整个子树正在等待布局并在任何位置调用requestLayout()
该子树的视图不会导致布局。只在该子树外的任何视图上调用requestLayout()
都会破坏该法术。
我考虑forceLayout()
的实施(以及它如何影响requestLayout()
,你不应该在你的代码中使用该功能。
答案 5 :(得分:2)
invalidate()
---> onDraw()
来自UI线程
postInvalidate()
---> onDraw()
来自后台线程
requestLayout()
---> onMeasure()
和onLayout()
并且不必 onDraw()
forceLayout()
---> onMeasure()
和onLayout()
只要直接父节点名为requestLayout()
。