Android 对 LayoutInflater.inflate()方法的深入理解

LayoutInflater.inflate() 方法有一个接收三个参数的方法重载

inflate(int resource, ViewGroup root, boolean attachToRoot)

第三个参数attachToRoot可能很多人疑问了很长时间,我之前也不太理解,那么先将结论说一下,稍后再做解释

  1. 如果root为null,attachToRoot将失去作用,设置任何值都没有意义。
  2. 如果root不为null,attachToRoot设为true,则会给加载的布局文件的指定一个父布局,即root。
  3. 如果root不为null,attachToRoot设为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性会自动生效。
  4. 在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true。

直接看结论的话,未必每一个人都能很容易的理解,下边举个例子说明

  • 先写一个activity_main.xml,这个布局文件很简单,只有一个空的LinearLayout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</LinearLayout>
  • 再写一个button_layout_1.xml,这个布局我们加入一个Button按钮,宽高固定,并且外层没有父Layout
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp"
    android:layout_height="50dp"
    android:text="Button">

</Button>
  • 最后写一个button_layout_2.xml,加入Button按钮,外层嵌套一个父Layout,父Layout的宽高固定
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp"
    android:layout_height="50dp">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />

</RelativeLayout>

方法1. 如果我们用以下代码来解析button_layout_1,那么中Button所设置的宽高是不生效的

ViewGroup mainLayout = (LinearLayout) findViewById(R.id.main_layout);
View buttonLayout = LayoutInflater.from(this).inflate(R.layout.button_layout_1, null);
mainLayout.addView(buttonLayout);

方法2. 而如果我们设置了inflate方法的root参数,并且attachToRoot设为true,那么Button所设置的宽高就生效了

ViewGroup mainLayout = (LinearLayout) findViewById(R.id.main_layout);
View buttonLayout = LayoutInflater.from(this).inflate(R.layout.button_layout_1, mainLayout, true);
// 不需要再addView
// mainLayout.addView(buttonLayout);

这是为什么呢?

首先,layout_width和layout_height 其实是用于设置View在布局中的大小的,也就是说,View必须存在于一个布局中,之后如果将layout_width、layout_height 设置成match_parent 或 wrap_content 或 固定的数值才会生效,这也是为什么这两个属性叫作layout_width和layout_height,而不是width和height

方法1中root设为null,Button外层又没有父Layout,所以Button所设置的宽高并没有生效

方法2中root设为mainLayout,attachToRoot设为true,会给加载的布局文件的指定一个父布局,所以Button的宽高就生效了,这也就对应了最上边的结论2

那么我们再来看button_layout_2

方法1. 设置root为null,Button的父布局RelativeLayout设置的宽高就无效

ViewGroup mainLayout = (LinearLayout) findViewById(R.id.main_layout);
View buttonLayout = LayoutInflater.from(this).inflate(R.layout.button_layout_2, null);
mainLayout.addView(buttonLayout);

方法2. 设置root设为mainLayout,attachToRoot设为false,Button的父布局RelativeLayout设置的宽高就生效了

ViewGroup mainLayout = (LinearLayout) findViewById(R.id.main_layout);
View buttonLayout = LayoutInflater.from(this).inflate(R.layout.button_layout_2, mainLayout, false);
mainLayout.addView(buttonLayout);

这也就对应了最上边的结论3:如果root不为null,attachToRoot设为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性会自动生效

好了,这下相信大家应该理解inflate()方法 attachToRoot参数的含义了吧!

Demo地址:https://github.com/jaycee88/LayoutInflaterDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容