view 的绘制过程

view的绘制包括三个过程:measurelayoutdraw

1measure:

整个View的组成可以看成是一棵树,measure过程是从根节点(PhoneWindow$DecorView)遍历所有节点,如果一个View还有子View,则measureView,直到所有的子View完成measure操作之后,再measure自己,也就是说measure操作是一个后序操作。由父节点给每一个节点的孩子节点节进行measure操作,即在ViewGroup中的measureChildWithMargin()中调用child.measure()方法,而根节点(PhoneWindow$DecorView)不需要measure,因为它默认占满了整个屏幕。然后执行到同一操作层次的onMeasure()方法,如果该View还有子View,则调用子Viewmeasure()方法。执行每一个非根节点需要走的measure过程:measure()->onMeasure()-> setMeasuredDimension()。这样,每一个view都知道了自己的大小。

其中,measure()/setMeasureDimension()View的最终类,不能被重载,onMeasure需要子View重载。按照前序遍历所有节点,但是最后设置每一个节点的大小(也就是调用SetMeasureDimension())的过程是后序设置的。



2)layout:

同理,再一次遍历,对每一个节点的孩子节点layout,根节点不需要layout。同样,每一个非根节点的节点需要走的layout过程:layout()->onLayout()。其中,layout()View的最终类,不能重载,onLayout()需要子View的重载。按照前序遍历所有节点,但是最后定位每一个节点的位置(也就是调用onLayout())的过程是后序定位的。



3draw:

measurelayout过程执行完成之后,从根节点开始draw,每一个节点(包括根节点)都需要这个draw的过程:draw()->drawbackground->onDraw()->dispatchDraw()->onDrawScrollBars().其中,draw(),onDrawScrollBars()View的最终类,不能重载,而onDraw被各种Widget(View的子类,如TextView,ImageView等)重载,负责画自己的视图。dispatchDraw()View的子类ViewGroup重载,负责画它的子View,即重复draw的过程,整个过程是一个递归过程。直到布局树中的叶子节点为止。画图过程是前序过程。

ListView的画图过程有些特殊,执行measure操作时,只是针对一个Item(它的子View)和它自己进行measure操作,待到执行onLayout()时再一并执行其余Itemsmeasurelayout操作。


你可能感兴趣的:(ListView,layout)