使用forceLayout(),requestLayout()和invalidate()

我对View类的forceLayout()requestLayout()invalidate()方法的angular色有些困惑。

他们什么时候被叫?

为了更好地理解由FrançoisBOURLIEUX和Dalvik提供的答案,我build议你看一下Arpit Mathur的这个令人敬畏的视图生命周期图: 在这里输入图像描述

invalidate()

调用invalidate()是当你想要安排重绘的视图。 这将导致onDraw最终被调用(很快,但不是立即)。 自定义视图将调用它的一个示例是当文本或背景颜色属性发生更改时。

该视图将重绘,但大小不会改变。

requestLayout()

如果关于你的视图的东西改变了会影响大小,那么你应该调用requestLayout() 。 这将触发onMeasureonLayout不仅为这个观点,而且一直为父视图的线。

调用requestLayout() 并不保证会导致onDraw (与接受的答案中的图相反),所以它通常与invalidate()组合在一起。

 invalidate(); requestLayout(); 

例如,自定义标签的文本属性已更改。 标签会改变大小,因此需要重新测量和重绘。

forceLayout()

当在父视图组上调用requestLayout() ,不需要重新测量和重新布局其子视图。 但是,如果一个孩子应该被包括在重新测量和重新布局中,那么你可以调用forceLayout()给孩子。 forceLayout()与其直接父对象上的requestLayout()一起出现,则forceLayout()仅适用于子对象。 调用forceLayout()本身不会起任何作用,因为它不会在视图树上触发requestLayout()

阅读这个Q&A的更详细的描述forceLayout()

进一步研究

  • 创build视图类:添加属性和事件 (有帮助的文档)
  • 查看文档
  • View源代码

在这里你可以find一些回应: http : //developer.android.com/guide/topics/ui/how-android-draws.html

对我来说,对invalidate()的调用只刷新视图,并调用requestLayout()刷新视图并计算屏幕上视图的大小。

您在要重绘的视图上使用invalidate(),它将调用onDraw(Canvas c),requestLayout()将使整个布局渲染(测量阶段和定位阶段)再次运行。 你应该使用它,如果你是在运行时改变子视图的大小,但只有在特定的情况下,像父视图的约束(我的意思是父高或宽是WRAP_CONTENT,所以匹配度量儿童,才可以包装他们再次)

这个答案对于forceLayout()是不正确的。

正如你可以在forceLayout()的代码中看到的那样,它只是将视图标记为“需要重新布局”,但它既没有调度也没有触发重新布局。 在未来的某个时候,重新布置将不会发生,因为某些其他原因,视图的父母被布置。

使用forceLayout()requestLayout()时,还有一个更大的问题:

假设你已经在视图上调用了forceLayout() 。 现在,在对该视图的后代调用requestLayout()时,Android将以recursion方式在该后代的祖先上调用requestLayout() 。 问题是,它将停止在你已经调用了forceLayout()的视图上的recursion。 所以requestLayout()调用将永远不会到达视图根,因此永远不会安排布局传递。 视图层次结构的整个子树正在等待布局,并且在该子树的任何视图上调用requestLayout()都不会导致布局。 只有在该子树以外的任何视图上调用requestLayout()才会中断该法术。

我会考虑执行forceLayout() (以及它如何影响requestLayout()被破坏,你不应该在你的代码中使用这个函数。