1.初识ViewRoot和DecorView
ViewRoot对应ViewRootImpl,是连接WindowManager和DecorView的桥梁。
DecorView其实是一个FrameLayout,一般情况下她的内部会包含一个LinearLayout,有上下两部分,上面是题目,下面是内容。

View绘制的三大流程(measure,layout,draw)都是通过ViewRoot完成的。
在ActivityThread中,当Activity创建完成之后,将DecorView添加到Window中,同时创建ViewRoot对象,将其和DecorView关联。
View的绘制是从VIewRoot的performTraversals方法开始的

*onMeasure():测量View的大小并且保存了测量的结果
* 我们首先来看该方法的定义:
* onMeasure(int widthMeasureSpec,int heightMeasureSpec)
注意:* 注意两个输入参数widthMeasureSpec和heightMeasureSpec不是一般的int而是MeasureSpec.
* MeasureSpec包含了specMode和specSize这两部分内容.
* 即specSize表示宽和高的大小,而specMode表示了宽和高的方式(规格).
* 其中,specMode有三种类型:
* 1 EXACTLY(具体的值为 1 << 30 即为:1073741824)
* 表示父视图希望子视图的大小应该是由specSize的值来决定的,系统默认会按照这个规则来设置子视图的大小
* 例如我们在xml文件中为控件的宽和高设置成一个具体的值或MATCH_PARENT时MeasureSpec的specMode就等于EXACTLY
* 2 AT_MOST(具体的值为 2 << 30)
* 表示子视图最多只能是specSize中指定的大小,开发人员应尽可能小得去设置这个视图,并且保证不会超过specSize
* 例如我们在xml文件中为控件的宽和高设置成WRAP_CONTENT的时候,MeasureSpec的specMode就等于AT_MOST
* 3 UNSPECIFIED(具体的值为 0)
* 表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制.
* 这种情况极少用到
1.2 我们看一下onMeasure()方法的源码:
* protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
* setMeasuredDimension(
* getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
* getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)
* );
* }
measure是静态final的方法不能重写,我们只能重写onMeasure()方法,另外,setMeaureDimension()方法用来保存测量好的尺寸大小,且该方法也是final的,只能使用。
getMeasureWidth()和getWidth()区别:
* 在onMeasure()和onLayout()结束之后,在此比较一下getMeasureWidth()和getWidth()的区别
* 1 获取的时机不一样
* getMeasureWidth()方法在onMeasure()结束后就可获取到
* getWidth()方法要在layout()过程结束后才能获取到
* 2 计算方式不一样.
* getMeasureWidth()的值是在setMeasuredDimension()方法已经设置好的.
* getWidth()方法中的值则是通过视图右边的坐标减去左边的坐标计算得出的.
* Draw
* 绘制图形界面.
* ViewRoot的performTraversals()方法会在layout()结束后调用View的draw()方法来执行此过程
* draw()一共有六步:
* Draw traversal performs several drawing steps which must be executed
* in the appropriate order:
* 1. Draw the background
* 2. If necessary, save the canvas' layers to prepare for fading
* 3. Draw view's content
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
*
* 第三步核心是onDraw()绘制内容
* 第四步的核心就是dispatchDraw()绘制子View
*
网友评论