安卓如果要注入布局 需要使用
这个方法的返回值是一个View 就是需要被注入到另一个布局的View ,但是这个方法可以填三个参数 也可以复写两个参数,点开LayoutInflater源码,我们可以看到,这个类实际上是Android提供的以Pull形式来解析xml布局文件,下面通过分别调用这个方法的三种形式具体分析一下这三个参数的作用LayoutInflater.from(context).inflate(resource,root,bollean);
首先画一个需要被注入进的子布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/item" android:background="#f88" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="这个一个item" android:layout_width="wrap_content" android:layout_height="250dp" /> <Button android:text="这是item的按钮" android:layout_width="wrap_content" android:layout_height="250dp" /> </LinearLayout>
这个item布局的效果图:
下面是Activity的布局文件 结构不复杂一个纵向的LinearLayout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linearlayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#05217b" android:orientation="vertical"> </LinearLayout>
1.三个参数第三个参数为true
在Activity中使用第一个方法
public class MainActivity extends AppCompatActivity { private LinearLayout linearlayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { linearlayout = (LinearLayout) findViewById(R.id.linearlayout); View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,linearlayout,true); } }
我们把第三个参数写成True 返回了一View 并没有向Activity中写addView();方法
现在运行一下代码看到的效果:
也就是说我们刚刚画的Item的View全部加入到了MainActivity中,并且指定了MainActivity的LinearLayout来作为itemView的根布局
这个方法总结一下就是 直接将第一个参数的layout布局文件加进第二个参数的指定布局(第二个参数的布局将会作为第一个参数的根布局),同时第一个参数的布局文件下面所有节点属性全部有效
2.三个参数第三个参数为false
我们将刚刚MainActivity中的inflate方法第三个参数改为false,其他的不去改变,这个时候,我们再去运行一下代码,会发现布局文件并没有被加载到第二个参数的布局中.
因此我们需要加上addView();方法再运行一次
public class MainActivity extends AppCompatActivity { private LinearLayout linearlayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { linearlayout = (LinearLayout) findViewById(R.id.linearlayout); View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,linearlayout,false); linearlayout.addView(itemView); } }
效果就跟第一个方法的效果一样了

其实如果第三个参数我们设置为false的话 系统不会给我们直接给加载出来的view直接注入到第二个参数的根布局中,需要我们再适当时候通过addView();方法将布局进行注入.
3.两个参数,第二个参数为空
下面将方法改为两个参数,第二个参数设置空 并跑一下代码看一下效果
public class MainActivity extends AppCompatActivity { private LinearLayout linearlayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { linearlayout = (LinearLayout) findViewById(R.id.linearlayout); View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,null); linearlayout.addView(itemView); } }
这回我们发现效果不一样了,我的itemView明明设置的match_parent的属性啊,为什么不充满MainActivity了呢? 那是因为我们第二个参数设置的是空 itemView最外层布局不知道自己的根布局是谁,通俗的说就是他找不到爸爸了 懵逼了,那他的match_parent属性就失效了,可是他里面包裹的子布局知道自己的爸爸就是现在这个懵逼的爸爸,所以按钮和文字的属性有效...
那么如果我不match_parent , 我直接给懵逼的布局一个固定宽高呢?那么我们再来试一下之后发现并没有什么卵用,高度依然不能铺满
总结一下第三个方法就是不给第一个参数设置根布局,第一个参数的布局文件的最外层布局属性失效,因为找不到爸爸了所以失效了,需要用addView();方法将返回的View添加到想添加的布局中.
其实如果看懂的小伙伴相信也明白了ListView在写适配器时候getView方法的使用了
最后
关于注入布局所延伸出来的知识点,通过几个大神的博客自己也有所启发:
1.我们在开发的过程中给控件所指定的layout_width和layout_height到底是什么意思?该属性的表示一个控件在容器中的大小,就是说这个控件必须在容器中,这个属性才有意义,否则无意义。这就总结了第三个方法和前两个的区别!
2.为什么Activity布局的根节点的宽高属性会生效?
其实原因很简单,大部分情况下我们一个Activity页面由两部分组成(Android的版本号和应用主题会影响到Activity页面组成,这里以常见页面为例),我们的页面中有一个顶级View叫做DecorView,DecorView中包含一个竖直方向的LinearLayout,LinearLayout由两部分组成,第一部分是标题栏,第二部分是内容栏,内容栏是一个FrameLayout,我们在Activity中调用setContentView就是将View添加到这个FrameLayout中.。而内容布局就是一个FrameLayout,这个布局的id叫作content,我们调用setContentView()方法时所传入的布局其实就是放到这个FrameLayout中的,这也是为什么这个方法名叫作setContentView(),而不是叫setView()。