摘要:
ViewGroup是一个特殊的View,它包含着其他的Views,属于布局的基类和Views容器。addView方法往ViewGroup添加子控件,removeView方法移除子控件。初始化布局使用LayoutInflater的inflate方法,有几种方式可以获取LayoutInflater对象,这里不讨论这个,我们来讨论inflate方法之间的区别。
一、inflate方法的区别
inflate(int,ViewGroup,boolean),解析一个xml布局文件,然后将其转换成View对象,int指定布局id,ViewGroup指定当前初始化View的父容器,boolean指定是否依附ViewGroup。inflate的另一个方法是inflate(int,ViewGroup),指定ViewGroup后,默认当前View依附父容器。到底依附父容器和不依附父容器有什么区别呢?指定ViewGroup与设置null又有什么区别?
inflate(int,ViewGroup)方法,初始化一个布局xml资源文件,指定ViewGroup的效果相当于往ViewGroup添加子控件,默认带两个参数的inflate依附于父容器。
查看带两个参数的inflate源码,如下:
- /**
- * Inflate a new view hierarchy from the specified xml resource. Throws
- * {@link InflateException} if there is an error.
- *
- * @param resource ID for an XML layout resource to load (e.g.,
- * <code>R.layout.main_page</code>)
- * @param root Optional view to be the parent of the generated hierarchy.
- * @return The root View of the inflated hierarchy. If root was supplied,
- * this is the root View; otherwise it is the root of the inflated
- * XML file.
- */
- public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
- return inflate(resource, root, root != null);
- }
内部调用的是带三个参数的inflate方法,如果指定了root,那么root!=null返回true,即childView隶属parentView的一个子控件。
如果将ViewGroup设置为null,初始化布局后,调用ViewGroup的addView,效果等同,代码如下:
- View childView=LayoutInflater.from(this).inflate(R.layout.activity_inflate_child,null);
- mParentView.addView(childView);
效果等同:
- LayoutInflater.from(this).inflate(R.layout.activity_inflate_child,mParentView);
inflate(int,ViewGroup,boolean)方法,多个一个boolean值,为true指定childView隶属parentView的一个子控件,否则ViewGroup仅用于创建正确的LayoutParams子类。查看源码解析,如下:
- /**
- * Inflate a new view hierarchy from the specified xml resource. Throws
- * {@link InflateException} if there is an error.
- *
- * @param resource ID for an XML layout resource to load (e.g.,
- * <code>R.layout.main_page</code>)
- * @param root Optional view to be the parent of the generated hierarchy (if
- * <em>attachToRoot</em> is true), or else simply an object that
- * provides a set of LayoutParams values for root of the returned
- * hierarchy (if <em>attachToRoot</em> is false.)
- * @param attachToRoot Whether the inflated hierarchy should be attached to
- * the root parameter? If false, root is only used to create the
- * correct subclass of LayoutParams for the root view in the XML.
- * @return The root View of the inflated hierarchy. If root was supplied and
- * attachToRoot is true, this is root; otherwise it is the root of
- * the inflated XML file.
- */
- public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
- final Resources res = getContext().getResources();
- if (DEBUG) {
- Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
- + Integer.toHexString(resource) + ")");
- }
- final XmlResourceParser parser = res.getLayout(resource);
- try {
- return inflate(parser, root, attachToRoot);
- } finally {
- parser.close();
- }
- }
分析源码,发现内部调用了inflate(XmlResourceParser,ViewGroup,boolean)方法,attachToRoot的英文翻译如上文一致,指定被初始化的view是否属于root的元素,如果被设置为false,root仅被用于创建合适的LayoutParams的子类
二、指定ViewGroup的另外一个作用:保证margin、padding属性生效
初始化一个xml布局资源,在初始化的布局root中指定了margin、padding属性,为了保证其生效,Viewgroup不能设置为null。下面具体来看一个例子:初始化多个activity_inflate_child,并添加到activity_inflate中,对比一个指定ViewGroup和没有指定ViewGroup之间的区别
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_marginTop="@dimen/activity_vertical_margin"
- android:layout_height="match_parent">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="指定子控件的父容器,margin、padding才生效"/>
- </LinearLayout>
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/activity_inflate_ll"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context="com.sinolvc.zspg.view.inflate.InflateChildActivity">
- </LinearLayout>
- /**
- * 添加第一个子控件,规则:设置ViewGroup
- */
- View childView = LayoutInflater.from(this).inflate(R.layout.activity_inflate_child, mParentView_ll, false);
- mParentView_ll.addView(childView);
- /**
- * 添加第二个子控件,规则:不设置ViewGroup
- */
- View childView2 = LayoutInflater.from(this).inflate(R.layout.activity_inflate_child, null, false);
- mParentView_ll.addView(childView2);
- /**
- * 添加第三个子控件,规则:设置ViewGroup
- */
- View childView3 = LayoutInflater.from(this).inflate(R.layout.activity_inflate_child, mParentView_ll, false);
- mParentView_ll.addView(childView3);
- /**
- * 添加第四个子控件,规则:不设置ViewGroup
- */
- View childView4 = LayoutInflater.from(this).inflate(R.layout.activity_inflate_child, null, false);
- mParentView_ll.addView(childView4);
最后运行的效果:
只有第一个和第三个View的margin、padding值生效,第二个和第四个没有设置ViewGroup,无效。
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/2094.html ,谢谢支持!