View是如何被添加到品目窗口上
- 创建顶层布局容器DecorView
- 在顶层布局中加载基础布局ViewGroup
- 将ContentView添加到基础布局中的FrameLayout中
View的绘制流程
绘制入口
ActivityThread.handleResumeActivity ->
WindowManagerImpl.addView(dercorView, layoutParams)->
WindowManagerGlobal.addView()
绘制的类及方法
ViewRootImpl.setView(decorView, layoutParams, parentView)->
ViewRootImpl.requestLayout()->scheduleTraversals()->doTraversal()->
performTraversals()
绘制的三大步骤
测量:ViewRootImpl.performMeasure
布局:ViewRootImpl.performLayout
绘制:ViewRootImpl.performDraw
View的绘制
MeasureSpec由SpecMode(前两位) + SpecSize(后三十位) 组成的32位int值
int MODE_SHIFT = 00000000000000000000000000000000;
// 父容器不对View做任何限制,系统内部使用
UNSPECIFIED = 0 << MODE_SHIFT; // 0
// match_parent
EXACTLY = 1 << MODE_SHIFT; // 01000000000000000000000000000000
// wrap_conent
AT_MOST = 2 << MODE_SHIFT; //10000000000000000000000000000000
View的测量-确定DecorView的MeasureSpec
DecorView的MeasureSpec由窗口大小和自身LayoutParams决定,遵守如下规则:
- LayoutParams.MATCH_PARENT:精确模式,窗口大小
- LayoutParams.WRAP_CONTENT:最大模式,最大为窗口大小
- 固定大小:精确模式,大小为LayoutParams的大小
View的MeasureSpec由父容器的MeasureSpec和自身LayoutParams决定
ViewGroup measure流程:
onMeasure(测量子控件的宽高) --> setMeasureDimension --> setMeasureDimensionRaw(保存自己的宽高)
View measure流程:
onMeasure --> setMeasureDimension --> setMeasureDimensionRaw(保存自己的宽高)
View的布局
- 调用view.layout确定自身的位置,即确定mLeft、mTop、mRight、mBottom的值。
- 如果是ViewGroup类型,需要调用onLayout确定子View的位置。
View的绘制
- 绘制背景drawBackground(canvas)
- 绘制自己onDraw(canvas)
- 绘制子view dispatchDraw(canvas)
- 绘制前景,滚动条等装饰onDrawForeground(canvas)