高级UI汇总目录
SeniorUI01_UI绘制流程分析(源码级分析)
SeniorUI04_UI绘制流程分析二应用(自定义标签流式布局)
SeniorUI05_UI绘制流程分析二应用(自定义标签流式布局)
#1 UI绘制流程的起始点
ViewRootImpl#performTraversals()
///测量
performMeasure()
// 摆放布局
performLayout()
// 绘制
performDraw()
#2 UI绘制流程
##一、Measure
MeasureSpec:在Measure流程中,系统将View的LayoutParams根据父容器所施加的规则转换成对应的MeasureSpec,在onMeasure中根据这个MeasureSpec来确定view的测量宽高
1)、测量模式
EXACTLY :父容器已经测量出所需要的精确大小,这也是childview的最终大小
----- match_parent,精确值
ATMOST : child view最终的大小不能超过父容器的给的
------ wrap_content
UNSPECIFIED: 不确定,源码内部使用
------- 一般在ScrollView,ListView
2)、测量大小:根据测量模式来确定测量大小
3)源码里面的位运算
&:取出对应Mask类型的属性值
|:添加对应的属性值
& =~与非 或者(^异或):去掉Mask类型的属性值
View的测量
onMeasure方法里面调用setMeasuredDimension()确定当前View的大小
ViewGroup的测量
1)遍历测量Child,可以通过下面三个方法来遍历测量Child
measureChildWithMargins
measureChild
measureChildren
2)setMeasuredDimension 确定当前ViewGroup的大小
3)假如去自定义View,ViewGroup,要如何做好Measure?
第一种:View的定义
套路:最终调用setMeasuredDimession方法来保存自己的测量宽高
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
/* Parent says we can be as big as we want. Just don't be larger
than max size imposed on ourselves.
*/
result = Math.min(desiredSize, maxSize);
break;
case MeasureSpec.AT_MOST:
// Parent says we can be as big as we want, up to specSize.
// Don't be larger than specSize, and don't be larger than
// the max size imposed on ourselves.
result = Math.min(Math.min(desiredSize, specSize), maxSize);
break;
case MeasureSpec.EXACTLY:
// No choice. Do what we are told.
result = specSize;
break;
}
return result;
第二种:ViewGroup
套路:
1、测量子view的规格大小
measureChildWithMargins
measureChild
measureChildren
2、通过子view的规格大小来确定自己的大小 setMeasuredDimession
##二、Layout布局过程
和Measure类似
#3 思考:
1、getWidth()和 getMeasuredWidth()在什么时候调用才会有值?
2、ScrollView里面嵌套Listview,ListView为什么只显示第一行的高度?
3、分析Draw的过程
4、自定义瀑布流—自定义ViewGroup来实现