安卓系统是如何绘制一个View的?How Android Draws Views

当Activity得到焦点后,就被要求画出它的布局。Android框架负责绘画的整个过程,但Activity必须提供布局的根结点。

绘画从根结点开始,它必须测量和画出布局树。 Drawing is handled by walking the tree and rendering each View that intersects the invalid region。

反过来,每一个ViewGroup负责请求每个子View去出它自己(用draw()),每一个子View负责把自己画出来。因为布局树从上到下依次访问,因此父结点先被画出来,兄弟结点再根据它们在树中出现的顺序,依次画出来。

画布局包括两个过程:测量过程和布局过程。测量过程在measure(int,int)方法中实现。并且从布局树的根结点到子孙结点。在自顶向下的递归过程中,每一个View都保存了自己的尺寸。第二个过程在layout(int, int ,int, int) 中实现,同样也是自顶向下调用。在这个过程中,父结点利用在测量过程中得到的尺寸来布局子结点。

当View的measure()方法返回时,它的getMeasuredWidth()和getMeasuredHeight()的值必须被设定,以给它的子孙使用。

子结点的measure width 和height必须严格限制在父结点的范围内。父结点可能调用measure()方法很多次。有不同的用途,主要是协调实际尺寸和子结点的尺寸。

测量过程利用两个类来交流尺寸信息。类View.MeasureSpec被View用来通知它的父结点,它想怎样来设定尺寸和定位。基本的LayoutParams类只是被

用来简单地描述想把宽和高设定为多大。对于每一个尺寸,可以设定为下面3种中的一个:

1.一个确定的数值。

2.FILL_PARENT。这意味着View想设定为同它的父结点一样大(减去边界)。

3.WRAP_CONTENT。这意味着View只想把大小设定为正好包含住自己的内容(加上边界;

每一个ViewGroup类有相应的LayoutParams子类,用来描述它的尺寸和定位信息。例如,RelativeLayout类有它自己的Layoutparams来使它的子结点View在水平

和垂直方向居中。

MeasureSpec被用来自顶向下(通过View tree)传递各种尺寸和定位需求。

每一个MeasureSpec能够是下列3种模型中的一个:

1.UPSPECIFIED。

2.EXACTLY。

3.AT_MOST。