android merge标签 的使用 和 遇到的坑

前言

在写一个功能时用到了动态加载  merge 标签的布局  因为原来都是直接在xml 用 include 直接使用  没有在代码里使用过  也没有仔细的了解过原理,因此直接掉坑里了   直接是用了日常布局的
复制代码
var view =     LayoutInflater.from(mContext)
.inflate(R.layout.dialog_commom_default_content,null)

layout.addView(view)
复制代码

来使用 结果一运行到这段代码就崩溃了,而后就仔细的了解了一下 merge 原理 请看下文:html

merge简介

merge标签是用来减小ui层级,优化布局的。
merge在通常状况下是用来配合include使用的
复制代码

以下:android

layout_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/app_bg"
    android:gravity="center_horizontal">

    <include layout="@layout/title"/>
</LinearLayout>

layout_title.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/delete"/>
</merge>
复制代码

这样使用的。 merge标签是怎么来减小层级的呢 ,在LayoutInflater的inflate()函数中解析时 发现解析的是 merge标签时会把merge 里的子元素直接添加到 merge的 父控件里 这样就减小了一个没有比较的容器控件了。 并且 merge 标签必须是根元素bash

merge遇到的坑

1.

在使用merge时给标签设置id 而后再代码里用findViewById去获取这个id view时 会出现崩溃的状况,这就是由于是用merge标签 在 LayoutInflater的inflate()函数中时直接将其中的子元素添加到了 merge 标签的 parent 中了,而merge 由于只是一个标签 因此是没有添加到 parent 里的,因此在运行时就没有这个merge 因此就会报错。app

在代码中经过代码添加 merge 标签布局 最早的时候是函数

var frameLayout =getView<FrameLayout>(R.id.fl_content)
if (!::view.isInitialized){
setConentLayout(LayoutInflater.from(mContext)
.inflate(R.layout.dialog_commom_default_content,null))
}
frameLayout?.addView(view,frameLayout.layoutParams )
复制代码

可是一运行这代码就会崩溃 这个是候用debug看了 在哪行代码发生的错误 是在布局

setConentLayout(LayoutInflater.from(mContext)
.inflate(R.layout.dialog_commom_default_content,null))
复制代码

2.

这里发生的错误,查看了一下源码 发现是由于inflate()函数中 添加的布局是 merge 布局是须要添加 在inflate()函数中传入 ViewGroup
由于在LayoutInflater 的inflate函数中有这个判断 当解析的是 merge标签时 若是这个 ViewGroup 为null 或attachToRoot 为false 就会直接抛出错误优化

if (TAG_MERGE.equals(name)) {
    if (root == null || !attachToRoot) {
        throw new InflateException("<merge /> can be used only with a valid "
                + "ViewGroup root and attachToRoot=true");
    }

    rInflate(parser, root, inflaterContext, attrs, false);
}
复制代码

解决了这个问题 代码改为这样ui

var frameLayout =getView<FrameLayout>(R.id.fl_content)
if (!::view.isInitialized){
setConentLayout(LayoutInflater.from(mContext)
.inflate(R.layout.dialog_commom_default_content,frameLayout,true))
}
frameLayout?.addView(view,frameLayout.layoutParams )

复制代码

我本觉得程序就能够愉快的跑下去了spa

3.可是我在一次运行时又报错了 此次错误是在

frameLayout?.addView(view,frameLayout.layoutParams )
复制代码

这一行里 ,可是我找了半天也没有找到问题所在 ,而后仔细看了一下源代码 发现是由于 在.net

LayoutInflater.from(mContext)
.inflate(R.layout.dialog_commom_default_content,frameLayout,true)
复制代码

的时候其实 merge 布局里的元素就已经添加进布局了 并且 这个返回的 View 就是咱们传入的 ViewGroup 因此个人这段代码 就是 把本身添加进本身 因此报错了

最后我改为如下代码就ok了

var frameLayout =getView<FrameLayout>(R.id.fl_content)
if (!::view.isInitialized){
setConentLayout(LayoutInflater.from(mContext)
.inflate(R.layout.dialog_commom_default_content,frameLayout,true))
}
复制代码

引用www.jianshu.com/p/cf3751333… www.androidchina.net/2485.html

相关文章
相关标签/搜索