Android中视图绘制流程的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
setContentView流程
setContentView整个过程主要是如何把活动的布局文件或者java的视图添加至窗口里,重点概括为:
- <李>
创建一个DecorView的对象mDecor,该mDecor对象将作为整个应用窗口的根视图。
李> <李>依据特性等风格主题创建不同的窗口修饰布局文件,并且通过findViewById获取活动布局文件该存放的地方(窗口修饰布局文件中id为内容的FrameLayout)。
李> <李>将活动的布局文件添加至id为内容的FrameLayout内。
李> <李>当setContentView设置显示好以后会回调活动的onContentChanged方法.Activity的各种视图的findViewById()方法等都可以放到该方法中,系统会帮忙回调。
李>Android的视图绘制
视图绘制主要包括三个方面:
- <李>
测量测量组件本身的大小
李> <李>布局确定组件在视图中的位置
李> <李>画根据位置和大小,将组件画出来
李>视图绘制的起点在ViewRootImpl类的performTraversals()方法,该方法完成的工作主要的是:,根据之前的状态,判定是否重新计算测试视图大小(测量),是佛重新放置视图位置(布局)和是否重新重绘视图(画),,部分源码如下:
private void performTraversals (), { ,,,,,,,,,,,,,,,,//最外层的根视图的widthMeasureSpec和heightMeasureSpec由来 ,,,,,,,//lp.width和lp.height在创建ViewGroup实例时等于MATCH_PARENT ,,,,,,,int childWidthMeasureSpec =, getRootMeasureSpec (lp.width mWidth也),,,,,,,,,int childHeightMeasureSpec =, getRootMeasureSpec (lp.height mHeight也); ,,,,,,…… ,,,,,,,mView.measure (childHeightMeasureSpec childWidthMeasureSpec也); ,,,,,,…… ,,,,,,,mView.layout (0, 0, mView.getMeasuredWidth (),, mView.getMeasuredHeight ()); ,,,,,,…… ,,,,,,,mView.draw(画布); ,,,,,,…… ,,,}
测量计算视图大小
几乎所有的组件都是继承视图类的,而关于视图的测量工作,日常开发用得多的方法就是衡量和onMeasure两个方法,测量不可重写,当我们自定义时主要重写onMeasure方法即可,在方法内部我们必须完成组件的mMeasuredWidth和mMeasuredHeight实际尺寸测量,而这个尺寸是需要父视图和子视图共同决定的
测量流程从根视图测量遍历整个视图树结构,如下:
MeasureSpec(View的内部类)测量规格为int型,值由高2位规格模式specMode和低30位具体尺寸specSize组成。其中specMode只有三种值:
MeasureSpec.EXACTLY //确定模式,父View希望子View的大小是确定的,由specSize决定;MeasureSpec.AT_MOST //最多模式,父View希望子View的大小最多是specSize指定的值;MeasureSpec.UNSPECIFIED //未指定模式,父View完全依据子View的设计值来决定;
View的measure方法是final的,不允许重载,View子类只能重载onMeasure来完成自己的测量逻辑。
最顶层DecorView测量时的MeasureSpec是由ViewRootImpl中getRootMeasureSpec方法确定的(LayoutParams宽高参数均为MATCH_PARENT,specMode是EXACTLY,specSize为物理屏幕大小)。