Skip to main content

Android LayoutInflater探究

PPLongAbout 2 min

LayoutInflater.inflate

项目中经常使用到LayoutInflater.inflate去加载Layout为View,那么三个参数到底有何意义,今天来仔细看一下.

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)

方法的含义肯定是明确的,即把定义好的layout的xml文件转化为View,同时设置该View是否有可参照的root,是否把该view添加进root中

首先看三个参数的含义

root != null && attachToRoot == true:

将resource指定的布局文件添加到root中,此时该布局文件的根布局的属性都是有效的。不需要再进行ViewGroup::addView操作

root != null && attachToRoot == false

这里可能会有疑问,既然我不添加到root中,那干嘛还要设置root呢?

这是因为有时候可能会借助于外部布局的参数

root == null

不管attachToRoot为何效果都是一样(不会自动帮你添加到当前根View中),并且此时需要手动addView,此时加载的布局文件的根布局中layout_height layout_width均会失效

自定义组装控件中的inflate问题

在自己创建View并指定布局文件时,尝试用

LayoutInflater.from(context).inflate(R.layout.item_test, this,true)

但其实不太清楚这是为什么,学习了刚刚上面的内容,应该比较清楚了。

举个例子,现在创建LinearLayout派生类CustomizeLayout,并创建自定义布局,包含一个LinearLayout与旗下的Button

  1. val inflate = LayoutInflater.from(context).inflate(R.layout.item_test, this, true)时

​ this即指代CustomizeLayout,此时在父布局中的结构: CustomizeLayout -> LinearLayout -> Button,且此 时布局效果均生效

  1. val inflate = LayoutInflater.from(context).inflate(R.layout.item_test, null) 且 addView(inflate)时

    此时父布局中结构: CustomizeLayout -> LinearLayout -> Button,且此时CustomizeLayout布局效果生效(在父布局中配置,肯定生效),但自定义布局文件中根布局宽高配置失效,因为inflate没有指定的root,因此宽高都是WRAP_CONTENT,适配内部组件宽高。

拓展

  • 自定义控件的xml中使用根布局merge标签能够避免布局重复问题
  • addView相同的view(引用相同),系统会报错。即一个Layout中不允许存在两个完全相同的View