根部:
Android framework 处理是从根节点开始,对布局进行measure和draw ,整个View树的绘制流程在ViewRoot.java类的performTraversals()函数展开
performTraversals:
1.是否需要重新计算视图大小measure,2.是否需要重新安置视图的位置layout,3.是否需要重新绘制draw
(measure测量)大小 -->(layout安排)位置 --> (draw绘制)内容
绘制顺序
- DecorView是根布局
- 然后按照树形图遍历,父view要measure自己之后再去遍历子view
measure 过程传递的两个类
- ViewGroup.LayoutParams(View自身的布局参数)
用来指定高度和宽度,getLayoutParams()会得到父view的layoutParams - MeasureSpecs类(父视图对自视图的测量要求)
测量和尺寸要求,有三个模式
UNSPECIFIED,没有约束
EXACTLY 确定尺寸
AT_MOST 父控件所给的最大尺寸,通常自定义
绘制流程
measure流程
view的 measure方法
- measure(int,int) 调用onMeasure(int,int),但是measure是final类,所以子类必须复写onMeasure。
onMeasure:
setMeasuredDimension():设置view的宽,高
getDefaultSize():返回测量后的大小,或者mMinWidth和Drawable最小宽度的最大值
ViewGrop的 measure方法
ViewGrop没有onMeasure()方法,但是定义了measureChildren
measureChildren:遍历所有children,获得子元素的属性
LinearLayout的measure流程
LinearLayout 是 ViewGrop的子类,他去实现ViewGrop没有实现的onMeasure,
mTotalLength 存储垂直高度,
wrap_content:计算所有元素,求和
match_parent:和view的测量一样
View的layout流程
传进来四个坐标点,坐标是对父布局来说的,并不是绝对做坐标
setFrame:设置四个顶点,然后执行onLayout
public void layout(int l, int t, int r, int b) {
...省略
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
...省略
}
onLayout: layoutVertical(l, t, r, b);或者 layoutHorizontal(l, t, r, b);
setChildFrame,遍历子布局
View的draw流程
-
View.draw(Canvas canvas)
ViewGrop没有复写,需要View.draw,但是自定义view一般是用onDraw进行绘制,也可以先进行super.draw进行系统的draw绘制,在进行自定义的onDraw绘制 -
View.onDraw()
默认空实现自定义需要自己复写方法,自己绘制 -
dispachDraw
viewGrop对子视图的绘制,自定义的ViewGrop不应该对dispachDraw进行复写 -
drawChild(cavans,this,drawingTime)
调用了 View 的child.draw(canvas, this,drawingTime)方法, -
invalidate
重绘draw树
dispatchDraw()–>drawChild()–>view.draw()
六个步骤
1.若有背景则绘制
2.保存canvas层
3.绘制自身内容
4.如果有子元素则绘制子元素
5.绘制效果
6.绘制装饰品(scrollbars)
来源:CSDN
作者:zafir.wu
链接:https://blog.csdn.net/wuzhen007/article/details/104609461