LayoutInflater的inflate()两种形式
LayoutInflater直译:布局填充器,我更喜欢称之为:打气筒。今天记录下我对inflate方法的使用理解。
LayoutInflater 的 inflate方法有如下两种:
public View inflate (int resource, ViewGroup root)
public View inflate (int resource, ViewGroup root, boolean attachToRoot)
查看源码,我们发现两个参数的方法内部引用了三个参数的方法
/**
* 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);
}
根据最后两个参数ViewGroup root是否为null及boolean attachToRoot的值可能为true或false,我们只需要研究四个方法:
inflater.inflate(R.layout.sub_view, null, false);
inflater.inflate(R.layout.sub_view, null, true);
inflater.inflate(R.layout.sub_view, parent, false);
inflater.inflate(R.layout.sub_view, parent, true);
对每个参数的解释
第一个参数@LayoutRes int resource
:想要添加的布局
第二个参数@Nullable ViewGroup root
:
想要添加到哪个布局上面。(root
为null
和有值的区别: 为null
时第一个参数中最外层的布局将会无效,有值的时候最外层的布局大小有效)
第三个参数boolean attachToRoot
:
是否直接添加到第二个参数布局上面。(true
代表布局文件填充的View
会被直接添加进parent
,而传入false
则代表创建的View
会以其他方式被添加进parent
)
验证
为验证以上理解,准备了:1.测试用的activity
的布局,也是父布局,parent_layout.xml
布局:
<?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/parent_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eee"
android:orientation="vertical"
tools:context=".MainActivity">
</LinearLayout>
2.子控件布局sub_view.xml
,其中最外层是RelativeLayout
,中间有一个TextView
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="vertical"
tools:context=".MainActivity"
android:background="#00f">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is subView"
android:layout_centerInParent="true"
android:background="#0f0"/>
</RelativeLayout>
形式1:inflater.inflate(R.layout.sub_view, null, false);
LinearLayout parentView = findViewById(R.id.parent_view);
View subView = LayoutInflater.from(this).inflate(R.layout.sub_view, null, false);
parentView.addView(subView);
效果如下:

形式2:inflater.inflate(R.layout.sub_view, null, true);
LinearLayout parentView = findViewById(R.id.parent_view);
View subView = LayoutInflater.from(this).inflate(R.layout.sub_view, null, true);
parentView.addView(subView);

形式3:inflater.inflate(R.layout.sub_view, parent, false);
LinearLayout parentView = findViewById(R.id.parent_view);
View subView = LayoutInflater.from(this).inflate(R.layout.sub_view, parentView, false);
parentView.addView(subView);

形式4:inflater.inflate(R.layout.sub_view, parent, true);
LinearLayout parentView = findViewById(R.id.parent_view);
View subView = LayoutInflater.from(this).inflate(R.layout.sub_view, parentView, true);
parentView.addView(subView);

意思是非法状态异常,指定的child已经有一个父容器了, 那就是你传入的parent。所以这种方式我们在使用的时候一定要注意:它会使代表layout文件填充的View会被直接添加进parent,如果我们使用这种方式后,在执行addView()方法就会造成上面的错误。
查看源码,可以看到:root != null && attachToRoot
时,内部已帮我们调用了addView了。所以会出现以上错误。
// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
root.addView(temp, params);
}
解决以上错误,我们就不需要我们手动调用addView方法了。修改如下:
LinearLayout parentView = findViewById(R.id.parent_view);
View subView = LayoutInflater.from(this).inflate(R.layout.sub_view, parentView, true);

总结:
1. inflater.inflate(R.layout.sub_view, null, false);
2. inflater.inflate(R.layout.sub_view, null, true);
1、2这两种方式运行结果一样,第二个参数传null会使要添加的布局视图中根视图的宽高设置失效,在使用这种方式的时候会造成我们无形中多加一层布局,为了使其子view显示相应高度。在这里不推荐使用
3. inflater.inflate(R.layout.sub_view, parent, false);
4. inflater.inflate(R.layout.sub_view, parent, true);
3.使最外层布局宽高有效;但不会自动添加parent布局。
4:这种方式我们在使用的时候一定要注意,它会使代表layout文件填充的View会被直接添加进parent,如果我们使用这种方式后,内部已帮我们调用了addView,再执行addView()方法就会造成上面的错误。
网友评论