zoukankan      html  css  js  c++  java
  • [译转]深入理解LayoutInflater.inflate()

    原文链接:https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/

    译文连接:http://blog.chengdazhi.com/index.php/110

    由于我们很容易习惯公式化的预置代码,有时我们会忽略很优雅的细节。LayoutInflater以及它在Fragment的onCreateView()中填充View的方式带给我的就是这样的感受。这个类用于将XML文件转换成相对应的ViewGroup和控件Widget。我尝试在Google官方文档与网络上其他讨论中寻找有关的说明,而后发现许多人不但不清楚LayoutInflater的inflate()方法的细节,而且甚至在误用它。

    这里的困惑很大程度上是因为Google上有关attachToRoot(也就是inflate()方法第三个参数)的文档太模糊:

    被填充的层是否应该附在root参数内部?如果是false,root参数只适用于为XML根元素View创建正确的LayoutParams的子类。

    其实意思就是:如果attachToRoot是true的话,那第一个参数的layout文件就会被填充并附加在第二个参数所指定的ViewGroup内。方法返回结合后的View,根元素是第二个参数ViewGroup。如果是false的话,第一个参数所指定的layout文件会被填充并作为View返回。这个View的根元素就是layout文件的根元素。不管是true还是false,都需要ViewGroup的LayoutParams来正确的测量与放置layout文件所产生的View对象。

    attachToRoot传入true代表layout文件填充的View会被直接添加进ViewGroup,而传入false则代表创建的View会以其他方式被添加进ViewGroup。

    让我们就两种情况多举一些例子来更深入的理解。

    attachToRoot是True

    假设我们在XML layout文件中写了一个Button并指定了宽高为match_parent。

    <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或Activity的LinearLayout中。如果这里LinearLayout已经是一个成员变量mLinearLayout了,我们只需要通过如下代码达成目标:

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

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

    下面的代码也有同样的效果。LayoutInflater的两个参数的inflate()方法自动将attachToRoot设置为true。

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

    另一种在attachToRoot中传递true的情况是使用自定义View。我们看一个layout文件中根元素有<merge>标签的例子。<merge>标签标识着这个layout文件的根ViewGroup可以有多种类型。

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

    这就是一个很好的使用attachToRoot的例子。这个例子中layout文件没有ViewGroup作为根元素,所以我们指定我们自定义的LinearLayout作为根元素。如果layout文件有一个FrameLayout作为根元素而不是<merge>,那么FrameLayout和它的子元素都可以正常填充,而后都会被添加到LinearLayout中,LinearLayout是根ViewGroup,包含着FrameLayout和其子元素。</merge>

    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);

    这两行代码与刚才attachToRoot为true时的一行代码等效。通过传入false,我们告诉LayoutInflater我们不暂时还想将View添加到根元素ViewGroup中,意思是我们一会儿再添加。在这个例子中,一会儿再添加就是在inflate()后调用addView()方法。

    在将attachToRoot设置为false的例子中,由于要手动添加View进ViewGroup导致代码变多了。将Button添加到LinearLayout中还是用一行代码直接将attachToRoot设置为true简便一些。下面我们看一下什么情况下attachToRoot必须传入false。

    每一个RecyclerView的子元素都要在attachToRoot设置为false的情况下填充。这里子View在onCreateViewHolder()中填充。

  • 相关阅读:
    《ASP.NET Core跨平台开发从入门到实战》Web API自定义格式化protobuf
    .NET Core中文分词组件jieba.NET Core
    .NET Core 2.0及.NET Standard 2.0
    Visual Studio 2017 通过SSH 调试Linux 上.NET Core
    Visual Studio 2017 ASP.NET Core开发
    Visual Studio 2017正式版离线安装及介绍
    在.NET Core 上运行的 WordPress
    IT人员如何开好站立会议
    puppeteer(二)操作实例——新Web自动化工具更轻巧更简单
    puppeteer(一)环境搭建——新Web自动化工具(同selenium)
  • 原文地址:https://www.cnblogs.com/ProtectedDream/p/6617846.html
Copyright © 2011-2022 走看看