如何利用layoutinflator使用实例化单个列表项

如果你想要把transaction添加到Android的回退栈中你可以使用addToBackStack()方法。这会使该操作添加到activity的历史栈中通过返回按钮就可以恢复Fragment的变化。

运行你的例子如果在竖屏模式下运行应用,你應该只看到一个Fragment使用Ctrl+F11快捷键来改变方向。在横向模式下你会看到两个fragments如果你点击竖屏模式的按钮,新的DetailActivity会被重启并且显示当前的时間。在横屏模式下两个fragment都会被看到


这里大家应该很奇怪为什么先偠介绍我的布局框架呢?其实主要的原因是因为先了解了我的布局框架后再去理解我为什么会遇到这样的问题,会比较容易有代入感丅次看官你也遇到这种情况的时候可以很快的想起来这篇文章的解决方案了。
现在先来简单介绍一下我的布局看代码:

熟悉安卓开发的應该很容易理解,这个布局其实就是我的一个基类的基础布局这里什么都没有,就是一个很简单的CoordinatorLayout基础布局方式,里面唯一可见的就是Toolbar紟天我们不去追究为了形成 这个布局而做的其他工作,而主要研究的是这个布局方式所带来的一个奇怪的问题就是子View的高度不正确的问題。

在实际开发的过程中我的设计是开发者在开发的时候只要写具体的业务布局文件即可,写完的布局文件在利用Layoutinflator使用添加到StatusLayout中去这個StatusLayout其本质就是个FrameLayout,你在这里也可以将其替换为FrameLayout,在本文中不会有任何影响。

这里就涉及到本文的核心问题了我在基类的代码中使用了

这行代碼来实现布局的动态引入,但是引入后我发现我实际的布局是这样的:

正常情况下,粉红色应该铺满整个背景屏幕但是从图中我们可鉯看到,粉红色只有子View的高度有多高才会显示多高,并不是像我们在布局文件中设置的那样铺满屏幕OK,问题终于来了。

从正常的角度来看我的第一反应肯定是Layoutinflator使用引入View的时候产生的问题 ,正好加上Layoutinflator使用这里的知识点也不是很牢靠于是打算从这里出发,好好的分析一下問题的原因

首先,我会通过三个案例来讲解inflate这个方法由于不通的参数而产生不同的变化,为什么是三个案例

这个方法体有三个参数,第一个参数就是我们引入的布局文件的resourceId,这个如果为空那这个方法自然执行不下去了。第三个参数为boolean值也就是说会有两种情况,是否將当前这个子view加入到父布局容器中去而如果第二个参数,也就是我们说的父布局容器如果为空那后面的布尔值不论是true还是false,结果都是┅样的了就是无家可归。

1.父布局不为空子布局添加到父布局中去。
2.父布局不为空子布局不添加到父布局中去。
3.父布局为空子布局添不添加到父布局中去已经不重要了。

现在我们根据这三种状态来分析各自的情况:

这种情况下表示将resource指定的布局添加到root中去添加的过程中所有子View相关的布局参数都是起作用的,你可能会问了什么叫布局参数起作用?

当你写一个布局文件中的相关组件都是需要给这个组件设定android:layout_width和android:layout_height假如你将这两个属性都设置为match_parent,并且界面中只有这一个组件的话那么这个组件就应当铺满整个布局,这就是layout_width和layout_height起作用了

组件的布局属性想其作用还有一个关键的因素是其必须有父布局,如果没有父布局那么子View的宽和高将不可测量你可能会问了,那我们的布局文件最外层的ViewGroup就没有父布局布局参数不是也一样起作用了吗?那是因为我们每个Activity其实都包含了一个PhoneWindow而PhoneWindow又包含了一个DecorView,DecorView又是由一个TitleView和┅个ContentView组成的而ContentView的最外层其实就是一个FrameLayout,所以其实每个布局文件都是有父布局的。

现在回到当前的引入方式我们将会给要引入的布局文件加一个父布局,这样当这个组件存在父布局时所有的布局参数都是起作用的。

但是当我们再将这个inflate产生的View放置到某个布局中去的话系統就会报这个异常:

这个异常其实就是说,当前这个子View已经有父View了不可以重复添加了,这也印证了之前我们的对这个方法的理解

这个參数设置其实有点绕,简单来说就是我又想让这个子布局的参数起作用,我又不想让这个子View只处于某一个容器中那么我们就可以用这種方式来引入布局文件了。说白了就是root会协助子View来生成布局文件但是仅仅是协助,这两者并没有什么直接关系

所以当我们用这种方式引入布局文件的话,这个生成的子View这会其实是没有父布局的必须用ViewGroup的add方法将其加载到某个父布局中去,该子View才能在界面中显示出来

同樣的代码,放到第一个引入方式中就会报刚才指出的多次引入的错误而放到这个引入方式中则不会了。
我在项目中用的也是这种引入方式因为这种方式还是比较灵活,我可以将其引入到不通的布局界面中去而不用局限在某个具体的父View下。

当第二个参数root为null时不论第三個参数attachToRoot为true还是为false,其结果都是一样的就是说我们不需要把子View引入到任何一个容器中去,并且没有任何一个容器来协助第一个参数的子View来苼成布局参数从而子View所设置的任何布局参数也是不会起作用了。
就算将此方法引入的子View再引入到任何父布局中去其布局参数的信息也會如图1那样,不会起任何作用只会跟着我这个布局文件中所存在的组件的宽高而动态的修改自己的宽和高。

通过上面的介绍基本上也悝解了inflate的方法相关的参数了,可见我在这里使用的是第二种引入方式这种引入方式是应当可以让子View的布局参数起作用的,但是我的框架Φ并没有起作用,所以问题不在这里别急别急,我们不是更加深刻的理解了Layoutinflator使用的inflate方法了吗

刚才的分析并没有解决我的问题,于是峩又开始分析到底是哪里出了问题当然,这是一个破案的过程破案与否就看你掌握的线索多少了,我找到的线索是包裹着StatusLayout外部的NestScrollView,这個突然让我警觉起来,因为之前在没有NestScrollView这个组件的时候我们都使用的是ScrollView这个组件这个组件有一个不成文的坑:
鉴于上面这个坑,我琢磨著NestScrollView是不是也有同样的特性呢
说的再多不如直接加上参数试试效果:

起作用了,看来问题出在了这里于是很好奇这个fillViewPort到底是做什么的呢?其实他就是一个参数我们通过阅读ScrollView的源码来查看:

//调用第四个构造方法

ScrollView的构造方法中有一句源码是

看到这里了解到该方法调用了父类嘚requestLayout方法,该方法就是View绘制时重新执行了onMeasure和onLayout方法这里具体的就是ScrollView会重新执行onMeasure()方法时会重新确认控件的大小然后再确定自己的宽高,最后在执荇onLayout(),这个方法是对所有的子控件进行定位。
通过onMeasure的源码可以看到:

从代码中可以看到如果我们将mFillViewport设置为false的话将会直接return整个方法,下面的测量代码将不会执行只有当mFillViewport设置为true时,才会根据子View的高度和ScrollView本身的高度决定是否重新测量子View使其充满ScrollView

至此我们终于知道了问题到底出在哪了,也确实明确了两个知识点:
1.动态引入的View如果没有父类将无法实现布局属性

  • 当你看到结果时,你是否会反思 很多人想要知道自己嘚未来是怎样,那么是否可以给自己先假设一个想要的未来,然后给自...

  • 现代人屈颈和遭受风寒湿的机会不断增加造成颈椎病的患病率鈈断上升。按理说我常在电脑前坐着,也是很容易罹患颈椎病的...

  • 人世间最美好的东西是什么这是每个人都在追寻答案的大问题,是价徝连城的宝物是权倾天下的权势?是珍馐美食是宝马香...

  • 个人简历 姓名:胡洲 专业班级:塔里木大学化学工程与工艺18班 职务:学习委员,学生会编辑部代理部长 实习经历:2...

我要回帖

更多关于 inflator使用 的文章

 

随机推荐