一篇弄懂LayoutInflater.from(context).inflate()

昨天项目的原因,使用到了这个LayoutInflater.from(context).inflate(),结果发现应该加载的布局没有显示出来。排查了好久发现是照着别人view的时候,直接把LayoutInflater.from(context).inflate(R.layout.item, null)照写了,然后就没加载出来。所以今天整理一下昨天出现的问题。

LayoutInflater.from(context).inflate()

这个方法有几个重载方法,其中主要使用的参数简单的解释一下。

1  int resource  代表需要加载资源的id

2 ViewGroup root 代表资源需要被添加的地方

3 boolean attachToRoot 是否要被添加到root中

4 XmlPullParser parser 代表xml文件

使用LayoutInflater.from(context).inflate()主要有两种方式,第一种是传入资源布局id,第二种是传入xml文件。分别如图所示

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
    return inflate(resource, root, root != null);
}

public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
        return inflate(parser, root, root != null);
    }

可以看到实际上这两种方式调用的都是带有attachToRoot的三个参数的重载方法。

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

通过源码我们可以看到实际上,通过资源id传入值,会将id转化成xml文件,所以其实底层都是将xml传入并进行绘制和加载。

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        …………
    }

由于这个方法代码太长了就不展示出来了,主要就是将xml文件进行解析,然后分别绘制。

再回顾一下带有两个参数的方法,他们的attachToRoot都是root != null,也就是如果root==null,就不添加(null没地方可以添加view);如果root!=null,换句话说如果view被指定了添加到哪个viewgroup中,那么attachToRoot默认为true。这很好理解。

如果上述例子太抽象,就举个例子

首先我有一个activity,它的布局文件和java代码如下。




package com.example.myapplication;

import android.view.LayoutInflater;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    LinearLayout mainContainer=findViewById(R.id.main_containter);
    LayoutInflater.from(this).inflate(R.layout.my_view,null);

  }
}

被添加的view 布局文件如下所示,很简单就是一个正方形的textview


  

运行效果如下所示

一篇弄懂LayoutInflater.from(context).inflate()_第1张图片

如果将代码改成

LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer);//相当于attachRoot=true

运行效果如下所示

一篇弄懂LayoutInflater.from(context).inflate()_第2张图片

可以发现,此时view被添加到了布局中并显示出来了。

再改一下,将attachRoot设置为false,可以猜想到view不会被添加到activity中。

    LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,false);

运行结果也如同我们到猜想。

一篇弄懂LayoutInflater.from(context).inflate()_第3张图片

此时再改变一下,通过addView添加。

    View view=LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,false);
    mainContainer.addView(view);

运行效果如同LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,ture)

一篇弄懂LayoutInflater.from(context).inflate()_第4张图片

通过这里的实验可以做一个推测

 View view=LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,false);
 mainContainer.addView(view);

等于

View view=LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,true);

这也反过来验证了attachRoot的作用就是将view添加到viewgroup中,作用和addview类似。

还有最后一个问题

LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,false) 和LayoutInflater.from(this).inflate(R.layout.my_view,null)有什么区别呢?

这里我们要知道,当我们设置layout_width和layout_height时必须在一个容器中才有意义。也就是说当我们上面的textview的宽高为100dp的时候,必须指定root才有效果,否则会失效。

看下面的例子

    view=LayoutInflater.from(this).inflate(R.layout.my_view,mainContainer,false);
    mainContainer.addView(view);

为了直观方便展示我们将这个view显示出来,效果如图所示,一切正常。

一篇弄懂LayoutInflater.from(context).inflate()_第5张图片

当我们这样设置时,可以发现有了变化,对于textview的宽高设置没有设置生效。

view=LayoutInflater.from(this).inflate(R.layout.my_view,null);
    mainContainer.addView(view);

一篇弄懂LayoutInflater.from(context).inflate()_第6张图片

最后可以看到,当不指定root时,需要添加的view所设置的布局属性会失效。至此应该算是搞懂LayoutInflater.from(context).inflate()三个参数的作用,以及他们分别的使用情况了。

你可能感兴趣的:(android,java,xml,linq,android)