之前一直对inflate里的ViewGroup参数感到困惑,知道看到了Dava Smith写的一篇关于这个inflate博客,才搞清楚inflate到底怎么用了。
以下是出自Dava Smith博客原文:
链接:http://possiblemobile.com/2013/05/layout-inflation-as-intended/
Layout inflation is the term used within the context of Android to indicate when an XML layout resource is parsed and converted into a hierarchy of View objects.
http://possiblemobile.com/2013/05/layout-inflation-as-intended/
It’s common practice in the Android SDK, but you may be surprised to find that there is a wrong way to use LayoutInflater, and your application might be one of the offenders. If you’ve ever written something like the following code using LayoutInflater in your Android application:

inflater.inflate(R.layout.my_layout, null);

PLEASE read on, because you’re doing it wrong and I want to explain to you why.

Get to Know LayoutInflater

Let’s first take a look at how LayoutInflater works. There are two usable versions of the inflate() method for a standard application:

inflate(int resource, ViewGroup root)
inflate(int resource, ViewGroup root, boolean attachToRoot)

The first parameter points to the layout resource you want to inflate. The second parameter is the root view of the hierarchy you are inflating the resource to attach to. When the third parameter is present, it governs whether or not the inflated view is attached to the supplied root after inflation.

It is these last two parameters that can cause a bit of confusion. With the two parameter version of this method, LayoutInflater will automatically attempt to attach the inflated view to the supplied root. However, the framework has a check in place that if you pass null for the root it bypasses this attempt to avoid an application crash.

Many developers take this behavior to mean that the proper way to disable attachment on inflation is by passing null as root; in many cases not even realizing that the three parameter version of inflate() exists. By doing things this way, we also disable another very important function the root view has…but I’m getting ahead of myself.

Examples from the Framework

Let’s examine some situations in Android where the framework expects you as a developer to interactively inflate portions of the view.

Adapters are the most common case for using LayoutInflater is custom ListView adapters overriding getView(), which has the following method signature:

getView(int position, View convertView, ViewGroup parent)
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

Have you noticed that every time the framework wants you to inflate a layout, they also pass you the parent ViewGroup it will eventually be attached to? Notice also that in most cases (including the above two examples), it will throw an Exception later on if LayoutInflater is allowed to automatically attach the inflated view to the root.

So why do you suppose we are given this ViewGroup if we are not supposed to attach to it? It turns out the parent view is a very important part of the inflation process because it is necessary in order to evaluate the LayoutParams declared in the root element of the XML being inflated. Passing nothing here is akin to telling the framework “I don’t know what parent this view will be attached to, sorry.”

The problem with this is android:layout_xxx attributes are always be evaluated in the context of the parent view. As a result, without any known parent, all LayoutParams you declared on the root element of your XML tree will just get thrown away, and then you’ll be left asking “why is the framework ignoring the layout customizations I defined? I’d better check SO and then file a bug.”

Without LayoutParams, the ViewGroup that eventually hosts the inflated layout is left to generate a default set for you. If you are lucky (and in many cases you are) these default parameters are the same as what you had in XML…masking the fact that something is amiss.

Application Example

So you claim you’ve never seen this happen in an application? Take the following simple layout that we want to inflate for a ListView row:

R.layout.item_row

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="?android:attr/listPreferredItemHeight"android:gravity="center_vertical"android:orientation="horizontal"><TextView
        android:id="@+id/text1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingRight="15dp"android:text="Text1" /><TextView
        android:id="@+id/text2"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="Text2" />
</LinearLayout>

We want to set the height of our row to be a fixed height, in this case the preferred item height for the current theme…seems reasonable.

However, when we inflate this layout the wrong way

public View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = inflate(R.layout.item_row, null);}return convertView;
}

we end up with a result that looks like this

What happened to the fixed height we set?? This is usually where you end up setting the fixed height on all your child views, switching the root elements height to wrap_content, and move on without really knowing why it broke (you may have even cursed at Google in the process).

If we instead inflate the same layout this way

public View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = inflate(R.layout.item_row, parent, false);}return convertView;
}

we end up with what we expected in the first place.

Hooray!

Every Rule Has An Exception

There are of course instances where you can truly justify a null parent during inflation, but they are few. One such instance occurs when you are inflating a custom layout to be attached to an AlertDialog. Consider the following example where we want to use our same XML layout but set it as the dialog view:

The issue here is that AlertDialog.Builder supports a custom view, but does not provide an implementation of setView() that takes a layout resource; so you must inflate the XML manually. However, because the result will go into the dialog, which does not expose its root view (in fact, it doesn’t exist yet), we do not have access to the eventual parent of the layout, so we cannot use it for inflation. It turns out, this is irrelevant, because AlertDialog will erase any LayoutParams on the layout anyway and replace them with match_parent.

AlertDialog.Builder builder = new AlertDialog.Builder(context);
View content = LayoutInflater.from(context).inflate(R.layout.item_row, null);builder.setTitle("My Dialog");
builder.setView(content);
builder.setPositiveButton("OK", null);
builder.show();

So the next time your fingers are tempted to just type null into inflate(), you should stop and ask yourself “do I really not know where this view will end up?”

Bottom line, you should think of the two parameter version of inflate() as a convenience shortcut to omit true as the third paramter. You should not think of passing null as a convenience shortcut to omit false.

  • With the two parameter version of this method, LayoutInflater will automatically attempt to attach the inflated view to the supplied root. However, the framework has a check in place that if you pass null for the root it bypasses this attempt to avoid an application crash.这句话指出inflate(int resource, ViewGroup root)这个方法,如果你提供了root,resource布局会自动添加到root布局中,然而系统会首先检查你是否传了空值,来避免应用崩溃。
  • Many developers take this behavior to mean that the proper way to
    disable attachment on inflation is by passing null as root; in many
    cases not even realizing that the three parameter version of
    inflate() exists. By doing things this way, we also disable another
    very important function the root view has…but I’m getting ahead of
    myself.这句话指出许多开发者经常这样使用inflater.inflate(R.layout.my_layout, null);
    ,没有意识到有三个参数的inflate存在,这样使用两个参数inflate的方法会让我们失去根视图的重要的功能。
  • So why do you suppose we are given this ViewGroup if we are not supposed to attach to it? It turns out the parent view is a very important part of the inflation process because it is necessary in order to evaluate the LayoutParams declared in the root element of the XML being inflated. Passing nothing here is akin to telling the framework “I don’t know what parent this view will be attached to, sorry.”这句话指出父视图是填充过程重要的部分,因为在计算被填充的XML布局的根元素定义的LayoutParams过程是必须要有父视图存在,如果给root传了空值,就相当于告诉了系统,它不知道这视图附在什么父视图上。 As a result, without any known parent, all LayoutParams you declared on the root element of your XML tree will just get thrown away,and then you’ll be left asking “why is the framework ignoring the layout customizations I defined? I’d better check SO and then file a bug.”指出没有任何一个已知的父视图的话,该结果会让你在XML根元素定义的LayoutParams参数全部会失效,为什么系统会忽视人家定义的布局参数呢?经过查看SO,发现它是一个bug来的。‘
  • Without LayoutParams, the ViewGroup that eventually hosts the inflated layout is left to generate a default set for you. If you are lucky (and in many cases you are) these default parameters are the same as what you had in XML…masking the fact that something is amiss.这句话指出在没有的LayoutParams情况下,最终控制填充布局的ViewGroup会产生一个默认LayoutParam值,大多情况下你很幸运遇到这些默认的值和你的XML LayoutParams值一样,但它遮盖了有时候会出错的事实。
  • The issue here is that AlertDialog.Builder supports a custom view, but does not provide an implementation of setView() that takes a layout resource; so you must inflate the XML manually. However, because the result will go into the dialog, which does not expose its root view (in fact, it doesn’t exist yet), we do not have access to the eventual parent of the layout, so we cannot use it for inflation. It turns out, this is irrelevant, because AlertDialog will erase any LayoutParams on the layout anyway and replace them with match_parent.这句话表明 inflater.inflate(R.layout.my_layout, null); 这样使用时正确的,因为填充布局附在dialog,dialog不存在根视图,因此我们最终不能使用其视图的父视图,经证实,AlertDialog会擦除任何layout的LayoutParams值,且使用match_parent替代。

  • -

Layout inflation的正确使用相关推荐

  1. 【安卓开发】Layout Inflation不能这么用

    Layout inflation在Android上下文环境下转换XML文件成View结构对象的时候需要用到. LayoutInflater这个对象在Android的SDK中很常见,但是你绝对没想到竟然 ...

  2. 一篇關於Android layout研究的文章[轉 from:http://blog.csdn.net/archimedes_zht/article/details/5333120]...

    Layout对于迅速的搭建界面和提高界面在不同分辨率的屏幕上的适应性具有很大的作用.这里简要介绍Android的Layout和研究一下它的实现. Android有4种Layout:FrameLayou ...

  3. HFSS 带状线仿真(HFSS和3D LAYOUT的比较)

    以前使用ANSYS还没有3D layout这个软件,现在有了这个以后,其实是对于PCB设计是非常方便,省去了繁琐的建模过程,那么实际这个软件和HFSS相差多少呢.我这里做了下对比. 今天使用带状线作为 ...

  4. Android Weekly Notes Issue #220

    Android Weekly Issue #220 August 28th, 2016 Android Weekly Issue #220 ARTICLES & TUTORIALS Manag ...

  5. Android点滴积累

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0717/3196.html 使用AndroidStudio一分钟实现Naviga ...

  6. 揭秘Context(上下文)

    最熟悉的陌生人--Context 刚刚学android或者js等,都会看见这个频繁的字眼--Context. 意为"上下文". 本文主要记述,Context到底是什么.如何理解Co ...

  7. Android性能优化之代码优化

    作为一个Android程序员,代码优化是最基本的能力.根据Android官方的建议,编写高效的代码的两个基本准则是: 不要做冗余的工作 尽量避免次数过多的内存分配操作 这里还有还有第三个准则:深入的理 ...

  8. Android lint检查

    一.什么是Android lint 检查 Android lint是一个静态代码分析工具,能够对项目中潜在的bug,可优化的代码,安全性,性能,可行性,可访问性,国际化等检查. 二.lint工作流程 ...

  9. Android Application中的Context和Activity中的Context的异同

    一.Context是什么: 1.Context是维持Android程序中各组件能够正常工作的一个核心功能类,我们选中Context类 ,按下快捷键F4,右边就会出现一个Context类的继承结构图啦, ...

  10. andorid 开发笔记 -- 问题与解决

    1. SQLiteDataBase 中 TimeStamp 转化为 Date 的问题:java.text.ParseException: Unparseable date: "Sun Jan ...

最新文章

  1. W3C XSL Transformations (XSLT) Version 2.0 翻译计划
  2. oracle rman和数据泵,使用RMAN或数据泵初始化OGG目标库
  3. LuaForUnity6:Lua模块
  4. 高校科研管理系统源代码_教育领域各大高校如何建设智慧校园?你的学校够数字化吗?...
  5. 斗地主发牌编程PHP,php模拟实现斗地主发牌
  6. RDL 报表 - 横向合并单元格后单元格被撑高
  7. MySQL 常见的 9 种优化方法
  8. rtx服务器插件的作用,腾讯通RTX手机版插件介绍 - 有度帮助中心
  9. Oracle Data Guard 简介
  10. 三维切面(水平面、冠状面、矢状面)的几种操作
  11. 《SQL必知必会》读书笔记上(第1~15章)
  12. 2022-2028年中国医药行业市场全面研究及前瞻分析报告
  13. Linux下使用ps命令查看某个进程文件的启动位置
  14. node.js实现编码转GBK转UTF8,中文乱码方案!!!
  15. FSB\QPI\DMI总线的区别
  16. css+js实现三维空间图片旋转,炫酷旋转
  17. 永磁同步电机无感控制“开环切闭环”的几点疑问
  18. Excel固定首行在滚动时不动
  19. 一些linux的记录
  20. 去除Win7兼容性 助手 对话框

热门文章

  1. mescroll.js -- 精致的下拉刷新和上拉加载js框架
  2. 拼多多商家无货源,如何批量铺货?
  3. ae怎么卸载已经安装的插件_ae红巨人插件卸载教程!
  4. 插头插座新旧标准对比和安规测试设备
  5. 测试打印机性能的软件,打印性能测试(一)
  6. A星(A*、A Star)路径规划算法详解(附MATLAB代码)
  7. 教你怎么利用Matlab画散点图
  8. java订餐管理系统代码,基于JAVA的订餐管理系统
  9. 斯坦福NLP名课带学详解 | CS224n 第6讲 - 循环神经网络与语言模型(NLP通关指南·完结)
  10. xposed框架在分机安装失败_pokemon go 和 虚拟gps