Android中每一个组件的绘制过程,都要经过三个阶段:测量、布局、绘制,分别对应着方法onMeasure、onLayout、onDraw(这三个方法定义于View类中)。当然,这三个方法都是允许组件自己重定义的方法,来实现组件对自己的尺寸进行测量(①有child views时,要分别对子组件调用相关测量方法,比如measureChild、measureChildWithMargins等,并根据子组件的dimension来确定自己的尺寸;②最后要调用setMeasuredDimension(measuredWidth, measuredHeight)方法来保存自己的尺寸信息。)、对自己进行布局(调用onLayout,如果是container,同样需要对子组件进行布局,调用子组件的layout(int l, int t, int r, int b)方法,最终同样会执行子组件的onLayout方法来实现对子组件的布局(布局说白了就是确定自己的绘制位置,即左上右下四个坐标),对于容器来说,将其中的具体组件布局好了,也就将其布局好了)以及绘制自己的内容(调用onDraw方法,使用该方法的参数Canvas进行内容绘制);
从代码中看,Android的绘图是从ViewRootImpl类的performTraversals方法开始的,可以把这个方法视为一个顶层的控制方法,在其中控制整个绘图的流程。具体情况如下所述:
Ⅰ首先,在其中会调用performMeasure方法,在performMeasure方法中调用View的measure方法(View的measure是final方法,方法原型为:
public final void measure(int widthMeasureSpec, int heightMeasureSpec),
也就是说不允许子类修改测量的框架,只能够修改真正进行测量工作的onMeasure方法),进而调用具体组件所实现的onMeasure方法。
Ⅱ然后,测量结束后会调用performLayout方法,在performLayout方法中调用View的layout方法,该方法原型为:
public void layout(int l, int t, int r, int b),
在该方法中会调用View的onLayout方法,对组件进行布局。
在拓展ViewGroup类的时候,对于所重写的onLayout方法,一般最后一步就是分别调用组件各自的layout方法来“Place the child.”。
Ⅲ之后,会调用performDraw方法,通过performDraw -> draw -> drawSoftware最终会调用View的draw(Canvas)方法。在draw方法中会有六步操作,在第三步“draw the content”时会调用onDraw(Canvas)方法,进行内容的绘制。