一篇弄懂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代码如下。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_containter"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

</LinearLayout>

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

<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="@+id/text"
android:layout_width="100dp"
android:layout_height="100dp"/>

运行效果如下所示

如果将代码改成

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

运行效果如下所示

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

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

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

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

此时再改变一下,通过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)

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

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显示出来,效果如图所示,一切正常。

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

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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值