本文仅简略地解释了onMeasure和onLayout的调用流程,不涉及调用过程中的参数意义的解释
+---------------------------+
| LinearLayout |
| |
| +-----------------------+ |
| | TextView | |
| | | |
| +-----------------------+ |
| +-----------------------+ |
| | TextView | |
| | | |
| +-----------------------+ |
+---------------------------+
[1]
假设当前Activity的页面层次架构如图[1]所示。一个LinearLayout中有两个TextView。
概述
总过程分两步:onMeasure过程和onLayout过程。onMeasure过程决定各个view的大小,onLayout过程决定view的位置。每个过程都从上往下地递归调用。
onMeasure过程
+--------------+ +--------------+ +--------------+
| LinearLayout | | TextView | | TextView |
+-------+------+ +-------+------+ +-------+------+
| | |
child.measure | | |
+--------------> | | |
[1] | | |
onMeasure | |
| child.measure | |
| +---------------> | |
| [2] onMeasure |
| | |
| | child.measure |
| +-------------------------------------->+
| | [3] |
| | onMeasure
| | setMeasureDimension
| | | [4]
| <---------+-----------------------------+
| | | |
| | | |
| | setMeasureDimension |
| | | |
setMeasureDimension +---------+ |
| [5] | |
| | |
<---------------+ | |
+ + +
- LinearLayout的父view/layout调用LinearLayout的measure方法,measure方法调用onMeasure方法。
-
onMeasure方法的目的是让layout(这里是LinearLayout)根据传入的两个MeasureSpec参数(代表父view当前分配给子view的Dimension),设置好自己‘想要’的Dimension大小。
-
Linearlayout怎么知道自己“想要”多大呢?必须要先知道自己的子view的“想要”大小。于是它会调用各个子view的measure方法。当子View分配好自己的大小后,便开始计算自己的大小,最后调用setMeasuredDimension方法保存“想要”的Dimension。计算完毕后直接返回父View。
-
值得注意的是,该过程(1-5)可能会调用多遍,来确认子view的大小(什么时候需要再次调用measure有待研究…)。
如图所示,LinearLayout首先要知道两个TextView的大小,然后根据结果调整自己的高度/宽度。
onLayout过程
+--------------+ +--------------+ +--------------+
| LinearLayout | | TextView | | TextView |
+-------+------+ +-------+------+ +-------+------+
| | |
| | |
| | |
child.layout | | |
+--------------> | | |
[1] | | |
| | |
| | |
onLayout | |
| [2] | |
| | |
| | |
| child.layout | |
| +---------------> | |
| [3] | |
| | |
| onLayout |
| | [4] |
| | |
| | child.layout |
| +-------------------------------------> |
| | |
| | onLayout
| | | [5]
| | |
+ + +
- LinearLayout的父view/layout调用LinearLayout的layout方法,layout方法调用onlayout方法。
-
对于ViewGroup来说,onLayout方法的意义是“决定子view的具体位置”,即ViewGroup通过调用子view的layout方法,传入4个参数(top,left,right,bottom),子view应该按照这四个参数渲染自己(draw)。
如图所示,LinearLayout告诉第一个TextView它所在的位置。第二个TextView的位置应该是原位置加上第一个TextView的高度(还有一些边距等)。
最后
- onMeasure和onLayout过程结束后,便开始递归调用onDraw方法渲染整个层次结构。
- AbsoluteLayout的源码十分简单,可以参考它来学习上述两个方法。