高级UI2-UI绘制流程(测量布局onMeasure)
前言
上一次我们讲到了最基本的android运行流程和绘制流程的调用顺序,我们最终得到一个结论是activity的生命周期是由系统服务所触发,由系统服务所发起handle调用到handleResumeActivity()开始绘制流程,最后交由给ViewRootImpl调用到performTraversals(),然后依次进行了我们UI的实际绘制流程measure(测量)、layout(布局摆放)、Draw(具体绘制),那么今天我们需要了解的是对UI具体的绘制流程measrue、layout、Draw进行深入分析,并且依托于今天所学的内容完成自定义瀑布流式布局。
View的测量流程
首先我们找到绘制流程当中的performTraversals()的测量布局方法:
performTraversals方法内部的performMeasure
performMeasure方法:
performMeasure
在这里我们可以看到当前他调用了view当中的测量,
那么这里我们先对测量方法中的参数进行分析,
在调用performMeasure调用之前需要两个参数:
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
他这里的意思是,传入宽高的测量规格,那么这个规格是什么意思?
进入到getRootMeasureSpec方法:
getRootMeasureSpec
这里我们看到了一个对象MeasureSpec,
MeasureSpec的作用是在Measure流程中,系统将View的layoutParams根据父容器所施加的规则转换成对应的MeasureSpec(规格),
然后在onMeasure中根据这个MeasureSpec来确定view的测量宽高,
MeasureSpec规定了设置宽高的几种模式:EXACTLY(match_parent)/ATMOST(wrap_content)/UNSPECIFIED,
MeasureSpec定义了一种数据结构(32位二进制),前两位是代表模式,后30位是size大小。
总结:整体的测量流程:在performTraversals开始获得DecorView中的系统布局的尺寸,然后在performMeasure方法中开始测量流程,对于不同的layout布局有着不同的实现方式,但大体上是在onMeasure方法中,对每一个子View进行遍历,根据ViewGroup的MeasreuSpec及子View的layoutParams来确定自身的测量宽高,然后最后根据所有子View的测量宽高信息,再确定爸爸的宽高,不断遍历子View的measure方法,根据ViewGroup的MeasureSpec及子View的LayoutParams来决定子View的MeasureSpec,进一步获取子View的测量宽高,然后逐层返回,不断保存ViewGroup的测量宽高。