\n\t\t\tView系统的绘制流程会从ViewRoot的performTraversals()方法中开始,performTraversals()的意思是:执行遍历
\n\t\t\tView的整个绘制流程可以分为以下三个阶段:
\n\t\t\tmeasure: 判断是否需要重新计算View的大小,需要的话则计算;
\n\t\t\tlayout: 判断是否需要重新计算View的位置,需要的话则计算;
\n\t\t\tdraw: 判断是否需要重新绘制View,需要的话则重绘制。
\n\t\t\tmeasure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。
\n\t\t\t总结:从以上分析可以看出View树的绘制是一个递归的过程,从ViewGroup一直向下遍历,直到所有的子view都完成绘制,那这一切的源头在什么地方(是谁最发起measure、layout和draw的)?当然就是在View树的源头了——ViewRoot!,ViewRoot中包含了窗口的总容器DecorView,ViewRoot中的performTraversal()方法会依次调用decorView的measure、layout、draw方法,从而完成view树的绘制。
\n\t\t\tonAttachedToWindow () 和 onDetachedFromWindow ()
\n\t\t\tonAttachedToWindow是在第一次onDraw前调用的。也就是我们写的View在没有绘制出来时调用的,但只会调用一次。
\n\t\t\tonDetachedFromWindow:销毁资源(既销毁view)之后调用。
\n\t\t\tveiw状态的保持:onSaveInstanceState()方法
\n\t\t\tAndroid View刷新机制
\n\t\t\t由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。
\n\t\t\t调用流程 :
\n\t\t\tmView.draw()开始绘制,draw()方法实现的功能如下:
\n\t\t\t绘制该View的背景
\n\t\t\t为显示渐变框做一些准备操作(见5,大多数情况下,不需要改渐变框)
\n\t\t\t调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)
\n\t\t\t调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup类已经为我们重写了dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。
\n\t\t\t在Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。这种处理逻辑在View的代码中明确的表现出来:
\n\t\t\t子View调用invalidate时,首先找到自己父View(View的成员变量mParent记录自己的父View),然后将AttachInfo中保存的信息告诉父View刷新自己。
\n\t\t\t总结回答:
\n\t\t\tmeasure()方法,layout(),draw()三个方法主要存放了一些标识符,来判断每个View是否需要再重新测量,布局或者绘制,主要的绘制过程还是在onMeasure,onLayout,onDraw这个三个方法中
\n\t\t\t1.onMesarue() 为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性: mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。
\n\t\t\t2.onLayout() 为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。
\n\t\t\t3.onDraw() 开始绘制图像,绘制的流程如下
\n\t\t\t首先绘制该View的背景
\n\t\t\t调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)
\n\t\t\t如果该View是ViewGroup,调用dispatchDraw ()方法绘制子视图
?
|