View的工作原理

2017-12-17  本文已影响6人  魂之挽歌w

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

*

上一篇 下一篇

猜你喜欢

热点阅读