[英]Usage of forceLayout(), requestLayout() and invalidate()
我对View
类的forceLayout()
、 requestLayout()
和invalidate()
方法的作用有点困惑。
什么时候叫他们?
为了更好地理解François BOURLIEUX和Dalvik提供的答案,我建议您看一下Arpit Mathur的这个很棒的视图生命周期图:
invalidate()
当您想要安排重绘视图时调用invalidate()
完成。 这将导致onDraw
最终被调用(很快,但不是立即)。 自定义视图何时调用它的一个例子是当文本或背景颜色属性发生变化时。
视图将被重绘,但大小不会改变。
requestLayout()
如果您的视图发生变化会影响尺寸,那么您应该调用requestLayout()
。 这不仅会触发此视图的onMeasure
和onLayout
,还会触发父视图的所有方式。
不能保证调用requestLayout()
会导致onDraw
(与已接受答案中的图表所暗示的相反),因此它通常与invalidate()
结合使用。
invalidate();
requestLayout();
例如,当自定义标签的文本属性发生更改时。 标签会改变大小,因此需要重新测量和重新绘制。
forceLayout()
当在父视图组上调用requestLayout()
时,不需要重新测量和重新布局其子视图。 但是,如果重新测量和重新布局中应包含子项,则可以对子项调用forceLayout()
。 forceLayout()
仅在与直接父级上的requestLayout()
一起出现时才对子级有效。 单独调用forceLayout()
不会有任何效果,因为它不会在视图树上触发requestLayout()
。
阅读此问答以获取有关forceLayout()
的更详细说明。
View
源代码在这里你可以找到一些回应:http: //developer.android.com/guide/topics/ui/how-android-draws.html
对我来说,调用invalidate()
只会刷新视图,调用requestLayout()
会刷新视图并计算屏幕上视图的大小。
invalidate()
---> 来自 UI 线程的onDraw()
postInvalidate()
---> 来自后台线程的onDraw()
requestLayout()
---> onMeasure()
和onLayout()
) 并且不一定是onDraw()
forceLayout()
---> onMeasure()
和onLayout()
当直接父级调用requestLayout()
时。
您在要重绘的视图上使用 invalidate() ,它将调用它的 onDraw(Canvas c) ,并且 requestLayout() 将使整个布局渲染(测量阶段和定位阶段)再次运行。 如果您在运行时更改子视图的大小,则应该使用它,但仅在特殊情况下使用,例如来自父视图的约束(我的意思是父高度或宽度为 WRAP_CONTENT,因此在子视图再次包装之前匹配测量子视图)
这个答案关于forceLayout()
是不正确的。
正如您在forceLayout()
的代码中看到的那样,它仅将视图标记为“需要重新布局”,但它既不安排也不触发该重新布局。 重新布局不会发生,直到在将来的某个时间点视图的父级由于某些其他原因而被布局。
使用forceLayout()
和requestLayout()
时还有一个更大的问题:
假设您在视图上调用forceLayout()
。 现在,当对该视图的后代调用requestLayout()
时,Android 将递归地对该后代的祖先调用requestLayout()
。 问题是它会在您调用forceLayout()
的视图上停止递归。 所以requestLayout()
调用永远不会到达视图根,因此永远不会安排布局传递。 视图层次结构的整个子树正在等待布局,并且在该子树的任何视图上调用requestLayout()
都不会导致布局。 只有在该子树之外的任何视图上调用requestLayout()
才会打破这个咒语。
我会考虑forceLayout()
的实现(以及它如何影响requestLayout()
被破坏,你不应该在你的代码中使用该函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.