使用LayoutInflator的inflate方法时会得到不同的结果

4
我想知道LayoutInflator上的LayoutParams是如何工作的。以及以下两者之间的区别:
LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, null); //FIRST WAY
LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, container,false); //SECOND WAY

因为这两种方法给我不同的结果。实际上,第二种inflate方法可以正确地显示两个子布局更改,但第一种方法会给出不同的结果。
以下是我的代码:
MainActivity.Java

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        LinearLayout mainLayout=(LinearLayout)findViewById(R.id.mainLayout);
        LayoutInflater inflater=LayoutInflater.from(getApplicationContext());
        for(int i=0;i<10;i++){
            LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, null); //First WAY
//          LinearLayout childLayout=(LinearLayout)inflater.inflate(R.layout.childitemlayout, mainLayout,false);  //SECOND WAY
            mainLayout.addView(childLayout);
        }
    }


main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

</LinearLayout>


childitemlayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:orientation="vertical" 
    android:background="#525f67">

    <TextView android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Button"
            android:gravity="center"
            />


</LinearLayout>  <!-- Both ways gives different result  --> 


<!-- 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" 
    android:background="#525f67">

    <TextView android:id="@+id/btn"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:text="Button"
            android:gravity="center"
            />


</LinearLayout> Both method gives SAME result   -->  
1个回答

12
两个inflate()方法的主要区别在于第二个参数(即ViewGroup参数)及其用法,用于为充气布局文件的根视图设置适当的LayoutParams。这很重要,因为LayoutParams保留视图的各种布局属性(如宽度、高度、定位规则等),必须以便该视图的父级可以正确显示视图。
第一个方法基本上是说:从此布局文件构建层次结构视图,但不将LayoutParams分配给膨胀层次结构的根(可能是因为尚不知道父级),也不将膨胀的视图附加到父级中
第二个inflate方法表示:从此布局文件构建层次结构视图,并向膨胀层次结构的根assign the proper LayoutParams(based on the second parameter given to the inflate method), 也不将膨胀的视图附加到父级中
在第一种情况下,膨胀的布局文件的根(R.layout.childitemlayout)不会有任何LayoutParams设置(inflate方法没有分配任何参数,因为第二个参数为null并且无法生成LayoutParams的类型),因此您的固定宽度/高度值丢失。稍后,当您执行mainLayout.addView(childLayout)时,mainLayout将检查childLayout的LayoutParams,看到这些LayoutParams为null,并自动设置LayoutParams的实例(使用其generateDefaultLayoutParams()方法)。在此特定情况下,对于水平LinearLayout,该方法将返回一个LayoutParams实例,其中宽度/高度将设置为WRAP_CONTENT。因此,您的childLayout最终将以WRAP_CONTENT作为其大小,而不是您设置的固定值。在第二种情况下,inflate方法看到你建议使用 LinearLayout 中的 mainLayout 作为生成 LayoutParamsViewGroup。这意味着从布局文件中检索出的固定值(用于宽度/高度)可以存储在适当的 LayoutParams 实例中。 当你执行 mainLayout.addView(childLayout);时,mainLayout 会看到 childLayout 具有适当的 LayoutParams 实例(该实例具有布局文件中使用的值),并且不会调用其 generateDefaultLayoutParams()方法。

非常感谢Luksprog的帮助。我接受了你的答案。再次感谢你提供这些有价值的信息。 - Amol Wadekar
1
这个答案的质量非常高,帮助我理解了很多。非常感谢你。我再怎么点赞也不为过。 - Makibo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接