彻底弄懂LayoutInflate.inflate()中三个参数与两个参数的意
义
1.三个参数的inflate⽅法
⽅法头如下:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
<⽤于给⽣成的view提供⼀个容器,有这个容器view的根布局的属性才会有意义,反之,没有这个容器,⽣成view的跟布局的属性就不起作⽤了(加深理解,正话反说);
c.attachToRoot代表是否把⽣成的view给⾃动增加到root这个容器上,这也意味着,如果root为空,则第三个参数,⽆论是true还是fal 也都没有意义了。当然,我们也可以吧⽣成的view给⼿动加到其他的view上⾯,这个看需求。
好,介绍了参数的意义,下⾯分为三种情况来讨论这个⽅法,分别来看
1.1 root不为null,attachToRoot为true
当root不为null,attachToRoot为true时,表⽰将resource指定的布局添加到root中,添加的过程中resource所指定的的布局的根节点的各个属性都是有效的。⽐如下⾯⼀个案例,我的Activity的布局如下:爱不悔
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"清理河道
android:id="@+id/ll"
tools:context="org.sang.layoutinflater.MainActivity">
</LinearLayout>
我还有⼀个布局l如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="/apk/res/android"
android:id="@+id/ll"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@color/colorPrimary"
3月用英语怎么说android:gravity="center"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
写生日的作文android:layout_height="wrap_content" />
浆汁
</LinearLayout>
我现在想把这个l布局⽂件添加到我的activity的布局中,那么我可以这么做:
@Override
protected void onCreate(Bundle savedInstanceState) {
tContentView(R.layout.activity_main);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.linearlayout, ll,true);
}
⼩伙伴们注意到,这⾥我都没写将inflate出来的View添加到ll中的代码,但是linearlayout布局⽂件就已经添加进来了,这就是因为我第三个参数设置为了true,表⽰将第⼀个参数所指定的布局添加到第⼆个参数的View中。最终显⽰效果如下:
如果我作死多写这么⼀⾏代码,如下:
protected void onCreate(Bundle savedInstanceState) {
tContentView(R.layout.activity_main);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.linearlayout, ll, true);
ll.addView(view);
}
领导小组这个时候再运⾏,系统会抛如下异常:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
变成的英文
原因就是因为当第三个参数为true时,会⾃动将第⼀个参数所指定的View添加到第⼆个参数所指定的View中。这⾥我们知道,在view树的层级结构中,⼀个view只可以有⼀个⽗view。
1.2 root不为null,attachToRoot为fal
如果root不为null,⽽attachToRoot为fal的话,表⽰不将第⼀个参数所指定的View添加到root中,那么这个时候有的⼩伙伴可能就有疑问了,既然不添加到root中,那我还写这么多⼲嘛?我第⼆个参数直接给null不就可以了?其实不然,这⾥涉及到另外⼀个问题:我们在开发的过程中给控件所指定的layout_width和layout_height到底是什么意思?该属性的表⽰⼀个控件在容器中的⼤⼩,就是说这个控件必须在容器中,这个属性才有意义,否则⽆意义。这就意味着如果我直接将linearlayout加载进来⽽不给它指定⼀个⽗布局,则inflate布局的根节点的layout_width和layout_height属性将会失效(因为这个时候linearlayout将不处于任何容器中,那么它的根节点的宽⾼⾃然会失效)。如果我想让linearlayout的根节点有效,⼜不想让其处于某⼀个容器中,那我就可以设置root不为null,⽽attachToRoot为fal。这样,指定root的⽬的也就很明确了,即root会协助linearlayout的根节点⽣成布局参数,只有这⼀个作⽤。OK,还是上⾯的布局⽂件,如果我想将之添加到activity的布局中⼜该如何呢?
protected void onCreate(Bundle savedInstanceState) {
tContentView(R.layout.activity_main);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.linearlayout, ll, fal);
ll.addView(view);
}
⼤家注意,这个时候我需要⼿动的将inflate加载进来的view添加到ll容器中,因为inflate的最后⼀个参数fal表⽰不将linealayout添加到ll 中。显⽰效果和上⽂⼀样,不再贴图。
1.3 root为null
当root为null时,不论attachToRoot为true还是为fal,显⽰效果都是⼀样的。当root为null表⽰我不需要将第⼀个参数所指定的布局添加到任何容器中,同时也表⽰没有任何容器来来协助第⼀个参数所指
定布局的根节点⽣成布局参数。我还是使⽤上⽂提到的linearlayout,我们来看下⾯⼀段代码:
protected void onCreate(Bundle savedInstanceState) {
tContentView(R.layout.activity_main);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.linearlayout, null, fal);
ll.addView(view);
}
当第⼆个参数为null,第三个参数为fal时(即使为true显⽰效果也是⼀样的,这⾥以fal为例),由于在inflate⽅法中没有将linearlayout添加到某⼀个容器中,所以我需要⼿动添加,另外由于linearlayout并没有处于某⼀个容器中,所以它的根节点的宽⾼属性会失效,显⽰效果如下:
⼩伙伴们注意,这个时候不管我给linearlayout的根节点的宽⾼设置什么,都是没有效果的,它都是包裹button,如果我修改button,则button会⽴即有变化,因为button是处于某⼀个容器中的。
2.两个参数的inflate⽅法
两个参数的inflate⽅法就很简单了,我们来稍微看⼀点点源码:
public View inflate(XmlPullParr parr, @Nullable ViewGroup root) {
return inflate(parr, root, root != null);
}
这是两个参数的inflate⽅法,⼤家注意两个参数实际上最终也是调⽤了三个参数。
两个参数的inflate⽅法分为如下两种情况:
<为null,等同于1.3所述情况。
<不为null,等同于1.1所述情况。
3.为什么Activity布局的根节点的宽⾼属性会⽣效?
inflate⽅法我们已经说完了,⼩伙伴们可能有另外⼀个疑问,那为什么Activity布局的根节点的宽⾼属
性会⽣效?其实原因很简单,⼤部分情况下我们⼀个Activity页⾯由两部分组成(Android的版本号和应⽤主题会影响到Activity页⾯组成,这⾥以常见页⾯为例),我们的页⾯中有⼀个顶级View叫做DecorView,DecorView中包含⼀个竖直⽅向的LinearLayout,LinearLayout由两部分组成,第⼀部分是标题栏,第⼆部分是内容栏,内容栏是⼀个FrameLayout,我们在Activity中调⽤tContentView就是将View添加到这个FrameLayout中,所以给⼤家⼀种错觉仿佛Activity的根布局很特殊,其实不然。丫髻岩
OK,以上就是对LayoutInflater中inflate⽅法的⼀个简单介绍,希望能够帮助到还没弄懂这个的⼩伙伴。
好好学习,加油!