LayoutInflater那些事儿
对于android初学者而言,看到LayoutInflater只能说是“爱过“。在自定义控件的时候构造函数中会LayoutInflater.from(mContext).inflater(layout_id, this);还有重写
适配器布局会LayoutInflater.from(getContext()).inflater(layout_id, null);当时我也是只知道这样用,具体怎么回事不是太清楚,今天就事论事,聊一聊LayoutInflater那些事儿。
首先我们要知道获取LayoutInflater实例有三种方式,并且本质都是一样的:
- LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()
- LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- LayoutInflater inflater = LayoutInflater.from(context);
读过源码的就会知道,三种最后都会执行到mContext.getSystemService()。
额,再来说说inflater方法,这个方法重载过一次,有两种形式:
- inflater(int resource, ViewGroup root);
- inflater(int resource, ViewGroup root, boolean attachToRoot);
然而第一种方法本质是inflater(int resource, ViewGroup root, root != null);所以这两个也是有联系的。
实践出真理,写个小demo,新建两个布局文件:
activity_main.xml:
<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="200dp" android:background="#555" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="测试" android:textColor="#abc" android:textSize="40sp" /></LinearLayout>
test.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="250dp" android:layout_height="match_parent" android:background="#478" android:orientation="vertical"></LinearLayout>
非常简单的两个布局,然后我们在MainActivity中编写:
View test = getLayoutInflater().inflate(R.layout.test, null);setContentView(test);
运行程序:
发现宽和高并不是我们自己定义的250dp,是不是巧合咧,改下代码:
View main = getLayoutInflater().inflate(R.layout.activity_main, null);setContentView(main);
呀哈,这就奇了怪了,为什么有这种情况,不要急,细细道来。
网上看源码分析的demo一搜几个G,我就不扯了,inflater(int resource, ViewGroup root, boolean attachToRoot)三个参数的意义:
- resource:不说也知道,布局的id
- root:该视图的根布局
- attachToRoot:是否将该视图添加到根布局中并返回
inflater的视图宽高,只有匹配到root根布局才会正常计算,不信你去看源码,反正我是信了。
只看解释可能没有什么说服力,那我们再修改代码:
View main = getLayoutInflater().inflate(R.layout.activity_main, null);View test = getLayoutInflater().inflate(R.layout.test, (ViewGroup) main);setContentView(test);
首先inflater一个main布局,因为root传的null所以宽高并不是我们自己定义的宽高,然后inflater一个test布局,这个布局传的root是main布局,后面的attachToRoot我没写出来,大家都应该知道是true吧,所以会正确的加载test布局,并把test布局添加到main布局中并返回。
有疑问,没关系,我们将
View test = getLayoutInflater().inflate(R.layout.test, (ViewGroup) main);
改成
View test = getLayoutInflater().inflate(R.layout.test, (ViewGroup) main, false);
按照上面的说法这里还是会正确加载test布局,但并不会将test添加到main布局中,我们再运行看看:
的确是这样,证明了我们上述的猜测是对的。
好了,如果你一行一行地看到了这里,相信你也明白了十之八九,好了,不知道大家有没有遇到一个问题,在自定义adapter中listview不能正常显示item的宽高,当初为了这个抓破头皮屑。。最简单的解决方法就是在不要穿root为空值,记得后面的参数传false哦。
可能见解看法有偏差,虚心接受大牛们的评教。
更多相关文章
- Android(安卓)RecyclerView控件
- 个人经验 - Android的RelativeLayout布局的layout_height属性设
- Android换肤Demo
- 关于Android(安卓)7.0下Launcher3下default_workspace.xml修改无
- ScrollView中的控件占据ScrollView的match_parent
- Android(安卓)Material Design Library系列教程(三)
- android studio 工程在android 源码编译
- [置顶] Android(安卓)ListView 基础入门 简介以及深入优化
- Android9.0版本Vold服务源码分析之上层处理SD卡挂载