LayoutParams是ViewGroup的一个静态内部类,封装了View的宽度和高度布局参数信息。
LayoutParams是子View用来告诉它的父控件如何放置自己的。如我们经常用到的以layout_xxx开头的一些属性,他们都是封装在对应父ViewGroup中对应的LayoutParams(如LinearLayout.LayoutParams)中。该LayoutParams作为成员变量存在子View中,并提供set和get方法。由此我们可以知道LayoutParams是和子View的父ViewGroup息息相关,脱离了父ViewGroup谈LayoutParams、谈子View的layout_xxx是毫无意义的(因为封装layout_xxx信息的是父ViewGroup的LayoutParams)。
ViewGroup中还定义了一个MarginLayoutParams继承于LayoutParams,字面理解它是和margin系列属性相关的,在LayoutParams的基础上增加了子View中的layout_marginxxx属性系列的支持。浏览源码我们可以得到:会优先取margin,如果没有,继续取horizontalMargin和verticalMargin,如果取不到,继续取left/right/top/bottom类型margin。优先级靠前的会覆盖靠后的,这也就可以解释我们在xml布局文件为一个view设置了layout_margin和left/right/top/bottom类型margin,后者无效。
另外,对于ViewGroup的每个子类都有自己的LayoutParams,如LinearLayout中的LinearLayout.LayoutParams,RelativeLayout中的RelativeLayout.LayoutParams等。 View中存在一个ViewGroup.LayoutParams类型的成员变量 mLayoutParams,这个成员变量什么时候赋值?当View被添加到它的父控件之前。
添加View一般有两种方式,1.通过xml添加;2.通过ViewGroup的addView()方法添加。
在xml中定义的view,首先会通过layoutinflater.inflate(),解析成对应的view实例。该方法存在多个重载,最终会调用inflate(XmlPullParase parase,ViewGroup root,boolean attachToRoot)。参数root表示xml文件的父view(可null),如果root为null,那么最后返回的是xml解析出来的根View=> temp,temp的mLayoutParams成员变量为null(因为不知道它的父ViewGroup是谁,自然也不知道它的父ViewGroup对应的layoutparams);如果root不为null,那么将调用root.generateLayoutParams(attrs)返回一个root类型ViewGroup的LayoutParams;此时如果attachToRoot为false,则将该值set给temp,最终返回temp;如果attachToRoot为true,则会调用root.addView(temp,params)(后面分析),将temp添加到它的父控件中,最终将root返回。
对于在Activity xml布局文件中定义的View,然后通过Activity的setContentView方法添加到容器中,其实它最终也是调用到LayoutInflater.inflate()来处理的。
第二种方式是通过addView()方法添加View。此时可分三种情况,1.view被实例化出来后已经设置过LayoutParams,2.View没有设置LayoutParams,但已经创建出来了,3.View没有设置LayoutParams,也没有创建出来(会通过generateDefaultLayoutParams()方法获取默认的,其中默认的宽高均设置为wrapcontent)。最终保证LayoutParams非空且合法,最后调用addView(View child, int index, LayoutParams params)这个方法。在这个方法中调用了requestLayout()和invalidate()方法,引起视图重新布局和重绘(视图结构发生了改变)。另外还调用了addInnerView方法,如果不希望引起子View重新布局就直接为子View的LayoutParams变量赋值(LayoutParams params=view.getLayoutParams();params.width=?,params.height=?);否则调用子View的setLayoutParams()方法传入新的Layoutparams。