LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)的使用

本文详细介绍了 LayoutInflater 中 inflate 方法的使用技巧。重点解析了 inflate 方法的三个参数:资源ID、父视图及附加标志的作用,并通过实例对比展示了不同参数设置下布局效果的变化。

LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)的使用

inflate(int resource, ViewGroup root, boolean attachToRoot)
第一个参数传入布局的资源ID,生成fragment视图,第二个参数是视图的父视图,通常我们需要父
视图来正确配置组件。第三个参数告知布局生成器是否将生成的视图添加给父视图。
root不为空的情况:
1.如果attachToRoot为true,就直接将这个布局添加到root父布局了,并且返回的view就是父布局
2.如果attachToRoot为false,就不会添加这个布局到root父布局,返回的view为resource指定的布局

root为空的情况:
View view = View.inflate(context, R.layout.button_layout, null);
其实等价于:LayoutInflater.from(this).layoutInflater.inflate(R.layout.button_layout, null);

那么root为不为空有什么影响呢?
1.如果root为null,attachToRoot将失去作用,设置任何值都没有意义。同时这个布局的最外层参数就没有效了
2.如果root不为null,attachToRoot设为false,则会将布局文件最外层的所有layout属性进行设置,
当该view被添加到父view当中时,这些layout属性会自动生效。
3.如果root不为null,attachToRoot设为true,则会给加载的布局文件的指定一个父布局,即root。

其实View必须存在于一个父布局中,这样layout_width和layout_height才会有效,
这也是为什么这两个属性叫作layout_width和layout_height,而不是width和height。
所以:inflate(int resource, ViewGroup root, boolean attachToRoot)的第二个参数不为空,resource的最外层布局参数才会有效,否则就无效了
例子:item的布局文件如下
复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="100dp">

    <TextView
        android:id="@+id/textView"
        android:textSize="30sp"
        android:gravity="center"
        android:background="#ffcccc"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
复制代码
 
     

如果我是这样加载这个布局:

View view= LayoutInflater.from(context).inflate(R.layout.recycler_item_layout,parent,false);

效果如下:  可见在item布局中设置的宽高都有效

如果我是这样加载布局:   

View view = View.inflate(context, R.layout.recycler_item_layout, null);

 效果图如下:   可见在item设置的宽高都无效,如果你在LinearLayout中设置宽高的长度为固定值100dp,这样也是没有效果的,但是如果是在TextView中设置宽高为固定值,这样是有效的

原因也就是layout_height是在父布局中的高度,你要是都没有父布局,它又怎么能知道你的match_parent是多大呢?,最后也就只能包裹内容了.

 

### 方法实现与用途解析:`public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)` 此方法是 Android 中用于解析 XML 布局文件并将其转换为实际的 `View` 对象的核心实现之一。它接收三个参数: - `XmlPullParser parser`:指向布局资源的 XML 解析器,用于读取布局文件的结构。 - `ViewGroup root`:作为解析后视图层次结构的父容器,如果 `attachToRoot` 为 `true`,则新解析的视图将被添加到此容器中。 - `boolean attachToRoot`:决定是否将解析后的视图附加到 `root` 容器中。 #### 核心逻辑 1. **找到 XML 根节点** 该方法首先通过 `advanceToRootNode(parser)` 定位 XML 文件中的根节点。通常,根节点是一个 `View` 标签,但也可能是 `<merge>` 标签。 2. **处理 `<merge>` 标签** 如果根节点是 `<merge>`,则必须在 `attachToRoot` 为 `true` 的情况下使用,否则会抛出异常。此时,`rInflate()` 方法会被调用以解析 `<merge>` 下的所有子节点,并直接将它们添加到 `root` 中。 3. **创建根 View** 通过 `createViewFromTag()` 方法,根据 XML 标签创建根 `View` 实例。例如,如果标签是 `LinearLayout`,则会创建一个 `LinearLayout` 实例。 4. **处理 LayoutParams** 如果 `root` 不为 `null`,则会从 `root.generateLayoutParams(attrs)` 生成 `LayoutParams`。如果 `attachToRoot` 为 `false`,则会将这些参数设置到临时视图上。 5. **递归解析子 View** 使用 `rInflateChildren(parser, temp, attrs, true)` 方法递归解析所有子视图,并将它们添加到当前视图中。 6. **决定是否将 temp 添加到 root** 如果 `attachToRoot` 为 `true`,则通过 `root.addView(temp, params)` 将解析后的视图添加到 `root` 中。 7. **返回值选择** - 如果 `attachToRoot` 为 `true`,返回 `root`,因为 `temp` 已经被添加到 `root` 中。 - 如果 `attachToRoot` 为 `false`,返回 `temp`,因为它没有被添加到 `root` 中。 #### 使用场景 - **非 null rootattachToRoot = true** 解析后的视图会自动添加到 `root` 中,适用于大多数需要将布局添加到现有容器的场景。 - **非 null rootattachToRoot = false** 解析后的视图不会自动添加到 `root` 中,但可能会继承 `root` 的 `LayoutParams`,适用于需要手动控制视图添加时机的场景。 - **null rootattachToRoot = false** 解析后的视图独立存在,不会有 `LayoutParams`,适用于 `Toast` 或 `Dialog` 等不需要嵌入到现有布局中的场景。 #### 示例代码 以下是一个典型的 `inflate` 方法调用示例: ```java View view = LayoutInflater.from(context).inflate(R.layout.my_layout, parent, false); ``` 在这个例子中,`R.layout.my_layout` 是要解析的 XML 布局资源,`parent` 是目标容器,`false` 表示不将解析后的视图立即添加到 `parent` 中。 #### 参数详解 - `parser`:指向 XML 布局文件的解析器,通常由 `Resources.getLayout()` 方法获取。 - `root`:目标容器,用于接收解析后的视图。 - `attachToRoot`:决定是否将解析后的视图附加到 `root` 容器中。 #### 内部实现片段 ```java public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { synchronized (this) { final AttributeSet attrs = Xml.asAttributeSet(parser); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // 跳过非 START_TAG 的事件 } if (type != XmlPullParser.START_TAG) { throw new InflateException(parser.getPositionDescription() + ": No start tag found!"); } final String name = parser.getName(); // 处理 merge 标签 if (TAG_MERGE.equals(name)) { if (root == null || !attachToRoot) { throw new InflateException("merge can be used only with a valid root and attachToRoot=true"); } rInflate(parser, root, attrs, false); } else { // 创建根 View final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null; if (root != null) { params = root.generateLayoutParams(attrs); if (!attachToRoot) { temp.setLayoutParams(params); } } rInflateChildren(parser, temp, attrs, true); if (root != null && attachToRoot) { root.addView(temp, params); } if (root == null || !attachToRoot) { result = temp; } } } return result; } ``` #### 总结 该方法是 Android 中视图解析的核心机制之一,广泛应用于布局加载、动态添加视图等场景。通过灵活控制 `attachToRoot` 参数,开发者可以实现不同的布局嵌套策略,满足多样化的 UI 需求[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值