Android中View的初步认识以及MeasureSpac的理解
View和DecorView
当Activity创建完毕时,会将DecorView添加到Window中,同时创建ViewRootImp对象,并将ViewRootImp对象与DecorView建立关联
如下代码所示:
root = new ViewRootImp(view.getContext(),display);
root.setVIew(view,wparams,panelParentView);
View的绘制是从ViewRoot的performTraversals方法开始的,经过measure,layout,draw三个流程才最终将一个view绘制出来,关于这三个流程的具体情况已经在
View工作流程之Measure
View工作原理之Layout过程和Draw过程
这两篇读后感中介绍了。
这三个流程大体的调用过程可以用一张图来总结,如下
DecorView的层级结构
DecorView作为我们的顶级View,一般内部包含了一个LinearLayout,在这个Layout中,又由两部分组成,顶部的TitleView和剩余部分的ContentView
如下图:
读到这里,想必大家终于明白了为什么在Activity中,设置内容布局的时候调用的函数是setContentView了,对,我们设置的其实就是这个ContentView的内容。
关于MeasureSpace
什么是MeasureSpec?
MeasureSpec其实是一个32位的int值, 由两部分组成,高2位代表SpecMode低30位代表SpecSize. 为什么这样做而不干脆设置成两个值呢?因为这样可以减少变量个数,从而达到减少开销的目的。
MeasureSpec的主要作用是在onMeasure流程中对测量控件大小提供信息,具体的信息就是上面的,mode和size,最终来确定控件到底是如何测量的。
MeasureSpec的SpecMode的三种模式
上面提到了SpecMode, 有三类,分别是,
UNSPECIFIED
父容器不对View有任何尺寸上的限制,一般用于系统内部,表示一种测量状态
EXACTLY
此时View的大小就是SpecSize指定的值,对应的就是match_parent和具体数值这两种模式。
AT_MOST
View的大小不能大于SpecSize,对应就是wrap_content
MeasureSpec和LayoutParams的对应关系
MeasureSpec的生成是通过自身的LayoutParams和父容器的MeasureSpec共同决定的。
由于DecorView是顶级View,所以其生成MeasureSpec的过程与普通View略有不同,是根据屏幕的大小以及自身的layoutparams来决定的
对于普通的View,在获得其SpecMesure时,首先会根据父容器的MessureSpec来拆分获得,mode,size两个值, 再结合自身的layoutparams来决定自己的MeasureSpec中的Mode和Size两个属性的值,最后生成自己的MeasureSpec值。
具体的生成对应可以参考作者在书中给出的表格
如下图:
至此,MeasureSpec就介绍完了,原本听起来高深莫测的东西,只要跟着这本书作者的思路一步步走下去,其实并不难懂。