Android笔记五(LayoutInflater)

LayoutInflater。Layout 布局,inflater,充气,填充,这个类用于将XML文件转换成相对应的ViewGroup和控件Widget等View。官方的解释为

  • Instantiates a layout XML file into its corresponding View objects. It is never used directly. Instead, use getLayoutInflater() or getSystemService(Class) to retrieve a standard LayoutInflater instance that is already hooked up to the current context and correctly configured for the device you are running on. For example:
LayoutInflater inflater = (LayoutInflater)context.getSystemService
      (Context.LAYOUT_INFLATER_SERVICE);

第一句翻译过来就是将layout布局文件实例化成一个View。在这里就和View类中的findViewById(R.id.xxxx)比较类似。事实上,在LayoutInflater类中也有类似的方法来完成这项工作:inflater.inflate()方法,下面对该方法进行具体的分析。
常用的inflate方法有以下两类重载

  1. public View inflate (int resource, ViewGroup root)
  2. public View inflate (int resource, ViewGroup root, boolean attachToRoot)

对于第一个方法,也就是把id为resource(R.layout.xxxx)的xml文件实例化成View,如果root不为空,则表示root为实例View的父容器,否则实例View本身作为父容器, 这点比较好理解。再看看返回值:

  • The root View of the inflated hierarchy. If root was supplied, this
    is the root View; otherwise it is the root of the inflated XML file.

最后返回的都是root view,也就是父容器
举个自定义栗子:

public class MyCustomView extends LinearLayout {
    ...
    private void init() {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    inflater.inflate(R.layout.view_with_merge_tag, this);
    }
}

这里的GroupView其实就是LinearLayout

对于第二个方法,多了一个attachToRoot参数。官方文档上的解释为:

  • boolean: Whether the inflated hierarchy should be attached to the
    root parameter? If false, root is only used to create the correct
    subclass of LayoutParams for the root view in the XML.
    被填充的层是否应该和root关联?如果是false,root参数只用作为XML根元素View创建正确的LayoutParams的子类,View本身作为父容器,(否则和上面的方法一样)

其实如果上面的难以理解,还能从返回值的定义来理解:

  • The root View of the inflated hierarchy. If root was supplied and
    attachToRoot is true, this is root; otherwise it is the root of the
    inflated XML file.

返回root View,如果root不为空 而且 attachToRoot为true,则root为父容器返回,否则(其他情况)View本身作为父容器。说了一大串,其实就是第一个方法内部其实也是由第二个方法实现的,内部调用第二个方法时,第三个参数为(root != null),如果还不知道怎么用,建议用第二个方法就可以了,选择性更大

下面分别对attachToRoot参数进行分析

attachToRoot为True而且root存在时

在xml文件中一个组件的布局代码如下:

<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/custom_button">
</Button>

把这个布局动态地添加到Fragment的的LinearLayout中,如果这里LinearLayout已经是一个成员变量mLinearLayout了,调用如下代码

inflater.inflate(R.layout.custom_button, mLinearLayout, true);

我们指定了用于填充button的layout资源文件,然后我们告诉LayoutInflater我们想把button添加到mLinearLayout中。这里Button的LayoutParams种类为LinearLayout.LayoutParams。

attachToRoot为False

我们看一下什么时候attachToRoot应该是false。在这种情况下,inflate()方法中的第一个参数所指定的View不会被添加到第二个参数所指定的ViewGroup中。
回忆一下刚才的例子中的Button,我们想通过layout文件添加自定义的Button至mLinearLayout中。当attachToRoot为false时,我们仍可以将Button添加到mLinearLayout中,但是这需要我们自己动手。

Button button = (Button) inflater.inflate(R.layout.custom_button, mLinearLayout, false);
mLinearLayout.addView(button);

这段代码和前一种情况等价
用源码中的一段代码来解释,你就会豁然开朗。所有inflate()方法最后都会调用这个方法:

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {  
    ...
            if (TAG_MERGE.equals(name)) {  
                ...
                rInflate(parser, root, attrs);  
            } else {  
                View temp = createViewFromTag(name, attrs);  
                ViewGroup.LayoutParams params = null;  
                if (root != null) {  
                    params = root.generateLayoutParams(attrs);  
                    if (!attachToRoot) {  
                        temp.setLayoutParams(params);  
                    }  
                }  
                rInflate(parser, temp, attrs);  
                if (root != null && attachToRoot) {  
                    root.addView(temp, params);  
                }  
                if (root == null || !attachToRoot) {  
                    result = temp;  
                }  
            }  
        } catch (XmlPullParserException e) {  
           ...
        } catch (IOException e) {  
           ...
        }  
        return result;  
    }  
}  

最后都是对root和attachToRoot的判断有木有!!!其中的createViewFromTag就是获取View实例,rInflate是个递归方法,不断遍历根布局(由createViewFromTag获取到,也就是源码中的temp)下的子View。

从源码中总结出来以下结论:

  1. root如果为空,表示需要我们自己执行root.addView(view),而且view的LayoutParams为空,也就是其xml中最外那层layout_xxx参数不生效。(PS:想想也是这样的道理,如果我们连父容器都没有,自己哪儿来的空间布局)
    这里写图片描述
  2. root不为空,表示我们view的LayoutParams有效。
  3. root不为空,attachToRoot为true,表示方法内部帮我们做了addView操作,不需要自己再添加

参考伯乐在线这篇还有CSDN这篇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值