View的工作流程:
1. measure
2. layout
3. draw
在View的类中有一个内部类 MeasureSpec 每一个View都有一个
从常量来看,MeasureSpec 是一个32位的值,高两位组成了 SpecMode 测量模式 后30位组成SpecSize 测量值
SpecMode 有三种模式:
1. UNSPECIFIED :不确定模式
2. AT_MOST:最大模式 wrap_content
3. EXACTLY:精确模式 match_parent
MeasureSpec 受自身的LayoutParams 以及父类的MeasureSpec影响,对DecorView没有父类,其MeasureSpec受自身的LayoutParams影响,以及窗口尺寸大小影响;
View的measure流程
onMeasure —— setMeasuredDimension (设置view的宽高)
getDefaultSize()根据不同的SpecMode返回不同的result值
在AT_MOST、EXACTLY模式下返回的是SpecSize这个值 说明对于一个直接继承与View的自定义view来说 wrap_content 与match_parent效果一致;
如果在UNSPECIFIED模式下,返回的值是View的最小值,在没有背景的情况下,返回的是mMinWidth,如果有背景,则是max(MMinWidth,mBackgroud.getMinimumWidth())
ViewGroup的measure流程:
ViewGroup不只是要测量自身,还需要遍历子类,并通过调用子类的measure方法对子view进行测量(继承ViewGroup的子类);
ViewGroup中没有实现onMeasure方法
但是有measureChildren()方法
measureChildren()
——measureChild
1. 通过子元素的LayoutParams、父类的MeasureSpec 来获取到子元素的MeasureSpec,在通过调用子元素的measure来进行测量
View的layout方法
layout方法是用来确定View的位置的,
ViewGroup中的layout方法用来确定子元素的位置,
View的layout方法用户确定自身的位置;
layout 流程:
1. setFrame(l,t,r,b) 给mLeft、mTop,mRight,mBottom 初始化赋值,基本确定view在父类中的位置;
2. 回调onLayout(),对view来说,onLayout只是一个空实现,一般不需要重载 但是对于ViewGroup来说,onLayout多了一个abstract要求其子类来必须重载onLayout方法,子类实现之后,遍历子元素,并调用子元素的layout方法
3. View的最终的布局位置和大小(mRight - mLeft = 实际宽 或 mBottom - mTop = 实际高) 完全由四个参数决定
measure过程 得到的mMeasuredWidth和mMeasureHeight提供了视图大小测量的值,但我们完全可以不使用这两个值,那么getMeasureWidth 与getWidth就可以能不是一个值
View的draw流程
- 如果需要绘制背景 // drawBackGround
- 保存当前的canvas(画布) //
- 绘制View的内容 // onDraw
- 绘制子View // dispatchDraw view是一个空方法,ViewGroup遍历子元素 并调用子元素的View.draw方法
5.如果需要绘制View的褪色边缘,阴影效果 //
6.绘制装饰 // onDrawScrollBars