LayoutInflater.inflate方法加载View

首先我们来看看关于布局加载,我们最先接触到的是setContentView()方法来完成的。我们还用到了LayoutInflater类来加载布局,其实setContentView()方法内部就是通过LayoutInflater实现布局加载的,只不过这部分源码是internal的,不太容易查到……
接下来就是LayoutInflater的基本用法了:
有两种方法可以获取到LayoutInflater实例,第一种如下:

1.  LayoutInflater layoutInflater = LayoutInflater.from(context);  

第二种方法如下:

1.  LayoutInflater layoutInflater = (LayoutInflater) context  
2.          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  

拿到实例后加载布局文件,有两个方法重载可以实现:
1.layoutInflater.inflate(int ResourceId,ViewGroup root)
2.layoutInflater.inflate(int ResourceId,ViewGroup root,boolean attachToRoot )
其实还有两个重载方法:
3.public View inflate(XmlPullParser parser, ViewGroup root)
4.public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)

主要就是root跟attachToRoot这俩参数的解析
1、 root是指给该布局的外部再嵌套一层父布局,如果不需要的话就指定为null;
2、 attachToRoot这个参数后面再讲
通过查看源码我们可以知道inflate方法内部是采用PULL方式解析XML文件,最后再返回最上层的布局标签,接下来我们说说inflate方法的第三个参数的作用,其实该参数要跟第二个参数root配合起来使用:
1、 如果root为null,attachToRoot为true,设置就没有任何意义;
2、 如果root不为null,attachToRoot为true,则会给加载的布局文件指定一个父布局,即root;
3、 如果root不为null,attachToRoot为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性就会自动生效;
4、 在不设置attachToRoot参数的情况下,如果root不为null,attachToRoot参数默认为true
划重点!!!
第二种和第三种情况是理解起来比较复杂的:
首先,我们看看第一种。如果root参数为null,那么后面的attachToRoot参数的设置就没有意义,也就是true,false都可以,随便填。
第二种情况,也就是root不为null,attachToRoot为true时,表示把布局的ID为resourceId的布局,加载到root中,此时记住:resource指定的布局的根节点,也就是该布局文件的xxlayout啊、xxView啊,他们的layout_xx属性,或者说所有属性就有效(因为基本所有属性都是有“layout_”这个字样)。
<~补充:
这里我们讲讲为什么属性layout_width、layout_height为什么不叫width、height呢?因为这些个属性啊,其实是标识自身控件在容器中的大小,这个控件必须在容器中,否则就会没有效果!
接着我们顺路讲一下setContentView这个方法,这个方法上面讲过,它是内部实现了layoutInflater的Inflate()方法,它加载布局时,会自动给布局外嵌套一层Fragment布局,这样,你要加载的布局的根布局就会全部生效,这个Fragment布局是系统自动帮我们加的,id为content,这就是为什么setContentView叫setContentView,而不是setView……这些我们在使用的时候根本不会注意到的点,其实底层已经作好了充分的封装,具体就体现在方法的命名上,只不过是我们忽视罢了
~>
第三种情况,即root不为空,attachToRoot为false时的情况。这种情况表示resource指定的布局不加载到root上,root和resource对应的布局没有任何关系!那跟root为空又有什么区别?别急~有了上面的补充啊,我们知道,如果我们要把resource指定的布局的根节点的layout_width和layout_height有效,那么我们是不是需要嵌套一层布局,如果我们又不想让它处于某个容器内,那么就可以设置root不为空,attachToRoot为false,这样resource布局和root没关系,resource里面的根节点属性也不会失效!

实例:
在布局文件activity_main.xml只设置了LinearLayout根布局:

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

我们再新增一个布局文件,layout.xml,里面只是添加一个按钮,其他布局就不要了:

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="180dp"
    android:text="@string/app_name"
    android:layout_height="180dp" />

我们在MainActivity中把layout中的View加载到activity_main.xml中:

package app.lhq.com.layoutinflatertest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class MainActivity extends AppCompatActivity {

    private LinearLayout linearLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        linearLayout = (LinearLayout) findViewById(R.id.linearLayout);

        LayoutInflater inflater = LayoutInflater.from(this);
        View button = inflater.inflate(R.layout.layout, null);
        linearLayout.addView(button);
    }
}

运行一遍,结果你会看到:
这里写图片描述
没什么问题吧?诶?不对,我们在按钮中设置的按钮的布局属性根本就没有生效啊!原因上面有讲到,其实就是inflate的带两个参数的方法,当第二个属性设置为null时,它就没有父布局可以依傍,所以,layout_xx属性全部失效~那么要怎么样才能使得button里面的布局生效呢?我们用到三个参数的inflate重载方法
修改参数值:

LayoutInflater inflater = LayoutInflater.from(this);
View button = inflater.inflate(R.layout.layout, LinearLayout,false);
linearLayout.addView(button);

上面方法的第三个参数如果设置为true的话,lineatLayout.addView(button)就可以不用写了,因为在该方法中已经add过一次了。
好了,在试一下运行,看看结果:
这里写图片描述
呐~生效了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值