一、View的绘制流程
View的绘制是在ViewRootImpl类里面进行的。该ViewRootImpl类是WindowManager连接DecorView的纽带。View的Measure、Layout、Draw都是在里面完成。ViewRootImpl通过PerformTraverals开始绘制先后经过以下流程:1、performMeasure–》measure–》onMeasure
2、performLayout–》layout–》onLayout
3、performDraw–》draw–》onDraw
二、DecorView的构成
DecorView是一个FrameLayout的子类它包含一个子LinearLayout。
LinearLayout下包含:1、titlebar 2、content 两个子View.其中content既是我们平时setContentview的内容
三、MeasureSpec
MeasureSpec的作用是帮助在onMeasure中获取父控件的值并根据父控件的MeasureSpec来控制自定义View的大小。MeasureSpec由SpecMode和SpecSize合成。
SpecMode表示Measure的模式:1、unspecified(系统测量) 2、Exactly(精确模式:Match_parent和确定值) 3、AT_MOST(对应Manifest的Wrap_Content)
通过makeMeasuerSpec进行合成,通过getSize()和getMode()进行分解
四、子View的MeasureSpec的生成规则
它是有父控件的MeaseurSpec和子View的LayoutParam来根据规则具体实现的
五、View的Measure过程
如果MeasurMode的值是Wrap_Content那么View必须自己实现它大小的测量,否则他的大小和Match_parent一样大
六、ViewGroup的Measure过程
ViewGroup没有对onMeasuer的默认实现。他需要在OnMeasure中调用MeasuerChildren后再根据自己的实际情况通过setMeasuredDimension来设置相应的大小
七、如何在Acitivty中动态的或去控件大小
因为Activity的生命周期和控件的初始化过程不同步,所以当需要测量控件大小时需要通过以下几种方法:
1、onWindowFocusChanged() 当窗体获得焦点时表示已经完成初始化
2、View.Post() 当消息队列开始执行时表示已经完成初始化
3、ViewTreeObserver 当View的内部可见性发生变化时表示初始化完成
八、onLayout的过程
getMeasureWidth和getWidth的区别:
getMeasureWidth代表的是在onMeasured的测量高度
getWidth表示的是最终高度,控件的最终大小由他来觉得
九、draw的过程
1、绘制背景
2、绘制自己
3、绘制children
4、绘制装饰(scrollbar)
ViewGroup默认不会调用onDraw()。所以需要通过setWillNotDraw来开启
十、自定义View须知
1、让View支持wrap_content
2、考虑view的padding和子view的margin
3、View自身有post功能所以尽量避免handler
4、若View中由动画需要在离开view前停止动画避免造成内存泄漏一般通过onDetachedFromWindow