美文网首页
54.Android LayoutInflater的inflat

54.Android LayoutInflater的inflat

作者: TensorFlow开发者 | 来源:发表于2019-11-16 13:25 被阅读0次

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
想要添加到哪个布局上面。(rootnull和有值的区别: 为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()方法就会造成上面的错误。

相关文章

网友评论

      本文标题:54.Android LayoutInflater的inflat

      本文链接:https://www.haomeiwen.com/subject/eycyictx.html