android view的工作原理(二)
View的工作流程主要是指mesaure , layout , draw这三大流程,即测量,布局,绘制。其中measure确定view的宽高,layout确定view的最终宽高和四个顶点位置,而draw则将view绘制到屏幕上。
1.meausre过程
如果只是一个原始的view,通过meausre方法就可以完成测量过程,如果是一个viewGroup,还需要遍历去调用所有子元素的meausre方法,各个子元素在递归去执行这个流程,
1)view的measure过程
在view的measure方法中会去调用view的onMeasure方法,onMeasure方法如下:
setMeasuredDimension方法会设置view宽高的测量值,
接下来我们看getDefaultSize方法:
我们只需要看AT_MOST,和EXACTLY这两种情况,其实getDefaultSize返回的大小就是measureSpec中的specSize,而这个specSize就是view测量后的大小,多次提到测量后的大小,是因为view最终的大小是在layout阶段确定的,但是几乎所有情况下view的测量大小就是最终的大小;
UNSPECIFIED这种情况,一般用于系统内部测量过程,view的大小为getDefaultSize的第一个参数size. getSuggestedMinimumWidth和getSuggestedMinimumHeight这两个方法的返回值。源码如下:
从代码中可以看出,如果view没有设置背景,那么View的宽高为minWidth,而mMinWidth对应android:minWidth属性所指定的值,因此view的宽度为android:minwidth,如果这个属性不指定,那么mWinwidth则默认为0.如果view指定背景,则View的宽度为max(mMinwidth,mBackground.getMinimumWidth()).
从上诉代码中我们知道: 如果view在布局中使用wrap_content,那么他的specMode是AT_MOST模式,在这种模式下,它的宽高等于specSize.
在上诉代码中,我们只需要给view指定一个默认的内部宽高(mWidth和wheight)并在wrap_content时设置此宽高即可,对于非wrap_content情形,我们沿用系统的测量值即可,至于这个默认的内部宽高大小如何指定,根据需求灵活指定即可。
2.viewGroup的measure过程
对于viewGroup来说,除了完成自己的measure过程外,还会遍历去调用所有子元素的measure方法,各个子元素在递归去执行这个过程,和view不同的是,viewGroup是一个抽象类,提供了一个叫measureChildren的方法,如图所示:
viewGroup在measure时,会对每一个子元素进行measure,measureChild方法如下:
MeasureChild的思想就是取出子元素的layoutParams,然后通过getChildeMeasureSpec来创建资源的measureSpec,接着将MeasureSpec直接传递给View的meausre方法进行测量,
3.分析linearLayout的measure
measureVertical的源码:
系统会遍历子元素对每个子元素执行measureCHildeBeforeLayout方法,这个方法会调用内部子元素的measure方法,这样各个子元素就依次进入measure过程,系统通过mTotalLenght这个变量来存储linearLayout在竖直方向初步高度,没测量一个子元素,mTotalLength就会增加,当子元素测量完毕,linearlayout会测量自己的大小。