关于inflate参数问题,我想很多人多多少少都了解一点,网上也有很多关于这方面介绍的文章,但是枯燥的理论或者翻译让很多小伙伴看完之后还是一脸懵逼,so,我今天想通过三个案例来让小伙伴彻底的搞清楚这个东东。本篇博客我们不讲源码,只看使用。源码的解读会在下一篇博文中带来。

inflate方法从大范围来看,分两种,三个参数的构造方法和两个参数的构造方法。在这两类中又有细分,OK,那我们就把各种情况都来演示一遍。

1.三个参数的inflate方法

方法头如下:

  1. public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)

好,这里主要分为三种情况,分别来看

1.1 root不为null,attachToRoot为true

当root不为null,attachToRoot为true时,表示将resource指定的布局添加到root中,添加的过程中resource所指定的的布局的根节点的各个属性都是有效的。比如下面一个案例,我的Activity的布局如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. android:id="@+id/ll"
  8. tools:context="org.sang.layoutinflater.MainActivity">
  9. </LinearLayout>

我还有一个布局linearlayout.xml如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/ll"
  4. android:layout_width="200dp"
  5. android:layout_height="200dp"
  6. android:background="@color/colorPrimary"
  7. android:gravity="center"
  8. android:orientation="vertical">
  9. <Button
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content" />
  12. </LinearLayout>

我现在想把这个linearlayout.xml布局文件添加到我的activity的布局中,那么我可以这么做:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. setContentView(R.layout.activity_main);
  5. LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
  6. LayoutInflater inflater = LayoutInflater.from(this);
  7. inflater.inflate(R.layout.linearlayout, ll,true);
  8. }

小伙伴们注意到,这里我都没写将inflate出来的View添加到ll中的代码,但是linearlayout布局文件就已经添加进来了,这就是因为我第三个参数设置为了true,表示将第一个参数所指定的布局添加到第二个参数的View中。最终显示效果如下:

如果我作死多写这么一行代码,如下:

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
  5. LayoutInflater inflater = LayoutInflater.from(this);
  6. View view = inflater.inflate(R.layout.linearlayout, ll, true);
  7. ll.addView(view);
  8. }

这个时候再运行,系统会抛如下异常:

  1. java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

原因就是因为当第三个参数为true时,会自动将第一个参数所指定的View添加到第二个参数所指定的View中。

1.2 root不为null,attachToRoot为false

如果root不为null,而attachToRoot为false的话,表示不将第一个参数所指定的View添加到root中,那么这个时候有的小伙伴可能就有疑问了,既然不添加到root中,那我还写这么多干嘛?我第二个参数直接给null不就可以了?其实不然,这里涉及到另外一个问题:我们在开发的过程中给控件所指定的layout_width和layout_height到底是什么意思?该属性的表示一个控件在容器中的大小,就是说这个控件必须在容器中,这个属性才有意义,否则无意义。这就意味着如果我直接将linearlayout加载进来而不给它指定一个父布局,则inflate布局的根节点的layout_width和layout_height属性将会失效(因为这个时候linearlayout将不处于任何容器中,那么它的根节点的宽高自然会失效)。如果我想让linearlayout的根节点有效,又不想让其处于某一个容器中,那我就可以设置root不为null,而attachToRoot为false。这样,指定root的目的也就很明确了,即root会协助linearlayout的根节点生成布局参数,只有这一个作用。OK,还是上面的布局文件,如果我想将之添加到activity的布局中又该如何呢?

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
  5. LayoutInflater inflater = LayoutInflater.from(this);
  6. View view = inflater.inflate(R.layout.linearlayout, ll, false);
  7. ll.addView(view);
  8. }

大家注意,这个时候我需要手动的将inflate加载进来的view添加到ll容器中,因为inflate的最后一个参数false表示不将linealayout添加到ll中。显示效果和上文一样,不再贴图。

1.3 root为null

当root为null时,不论attachToRoot为true还是为false,显示效果都是一样的。当root为null表示我不需要将第一个参数所指定的布局添加到任何容器中,同时也表示没有任何容器来来协助第一个参数所指定布局的根节点生成布局参数。我还是使用上文提到的linearlayout,我们来看下面一段代码:

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
  5. LayoutInflater inflater = LayoutInflater.from(this);
  6. View view = inflater.inflate(R.layout.linearlayout, null, false);
  7. ll.addView(view);
  8. }

当第二个参数为null,第三个参数为false时(即使为true显示效果也是一样的,这里以false为例),由于在inflate方法中没有将linearlayout添加到某一个容器中,所以我需要手动添加,另外由于linearlayout并没有处于某一个容器中,所以它的根节点的宽高属性会失效,显示效果如下:

小伙伴们注意,这个时候不管我给linearlayout的根节点的宽高设置什么,都是没有效果的,它都是包裹button,如果我修改button,则button会立即有变化,因为button是处于某一个容器中的。

2.两个参数的inflate方法

两个参数的inflate方法就很简单了,我们来稍微看一点点源码:
  1. public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
  2. return inflate(parser, root, root != null);
  3. }

这是两个参数的inflate方法,大家注意两个参数实际上最终也是调用了三个参数。

两个参数的inflate方法分为如下两种情况:
1.root为null,等同于1.3所述情况。
2.root不为null,等同于1.1所述情况。

3.为什么Activity布局的根节点的宽高属性会生效?

inflate方法我们已经说完了,小伙伴们可能有另外一个疑问,那为什么Activity布局的根节点的宽高属性会生效?其实原因很简单,大部分情况下我们一个Activity页面由两部分组成(Android的版本号和应用主题会影响到Activity页面组成,这里以常见页面为例),我们的页面中有一个顶级View叫做DecorView,DecorView中包含一个竖直方向的LinearLayout,LinearLayout由两部分组成,第一部分是标题栏,第二部分是内容栏,内容栏是一个FrameLayout,我们在Activity中调用setContentView就是将View添加到这个FrameLayout中,所以给大家一种错觉仿佛Activity的根布局很特殊,其实不然。

【转】三个案例带你看懂LayoutInflater中inflate方法两个参数和三个参数的区别的更多相关文章

  1. 三个案例带你看懂LayoutInflater中inflate方法两个参数和三个参数的区别

    关于inflate参数问题,我想很多人多多少少都了解一点,网上也有很多关于这方面介绍的文章,但是枯燥的理论或者翻译让很多小伙伴看完之后还是一脸懵逼,so,我今天想通过三个案例来让小伙伴彻底的搞清楚这个 ...

  2. 带你看懂LayoutInflater中inflate方法

    关于inflate问题,我想很多人多多少少都了解一点,网上也有很多关于这方面介绍的文章,但是枯燥的理论或者翻译让很多小伙伴看完之后还是一脸懵逼,so,我今天想通过三个案例来让小伙伴彻底的搞清楚这个东东 ...

  3. 一文带你看懂Java中的Lock锁底层AQS到底是如何实现的

    前言 相信大家对Java中的Lock锁应该不会陌生,比如ReentrantLock,锁主要是用来解决解决多线程运行访问共享资源时的线程安全问题.那你是不是很好奇,这些Lock锁api是如何实现的呢?本 ...

  4. 从源码带你看懂functools的partial方法

    1.what? partial是什么, partial也叫偏函数.源码的描述是: 部分应用给定参数和关键字的新函数. New function with partial application of ...

  5. 【 全干货 】5 分钟带你看懂 Docker !

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者丨唐文广:腾讯工程师,负责无线研发部地图测试. 导语:Docker,近两年才流行起来的超轻量级虚拟机,它可以让你轻松完成持续集成.自动交付 ...

  6. 一篇带你看懂Flutter叠加组件Stack

    注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 Stack Stack组件可以将子组件叠加显示,根据子组件 ...

  7. 转://看懂Oracle中的执行计划

    一.什么是Oracle执行计划? 执行计划是一条查询语句在Oracle中的执行过程或访问路径的描述 二.怎样查看Oracle执行计划? 2.1 explain plan for命令查看执行计划 在sq ...

  8. 一文看懂js中元素偏移量(offsetLeft,offsetTop,offsetWidth,offsetHeight)

    偏移量(offset dimension) 偏移量:包括元素在屏幕上占用的所有可见空间,元素的可见大小有其高度,宽度决定,包括所有内边距,滚动条和边框大小(注意,不包括外边距). 以下4个属性可以获取 ...

  9. LayoutInflater.inflate()方法两个参数和三个参数

    转载请标明出处:https://www.cnblogs.com/tangZH/p/7074853.html  很多人都用过LayoutInflater(布局填充器) 对于我来说通常使用下面两种:Lay ...

随机推荐

  1. Linux shell编程-退出的状态码

    linux 提供了一个专门的变量$?来保存上个已执行命令的状态码 linux 的错误状态退出状态码没有什么标准可遵循,但有一些参考 状态码 描述 0 命令成功结束 1 一般性未知错误 2 不适合的sh ...

  2. shuffle的工作原理

    Shuffle的正常意思是洗牌或弄乱,可能大家更熟悉的是Java API里的Collections.shuffle(List)方法,它会随机地打乱参数list里的元素顺序.如果你不知道MapReduc ...

  3. Android中RadioGroup的初始化和简单的使用

    一简介: RadioGroup作为一个单选按钮组,可以设置为性别选择男或则女,地址选择等等,作为一个android入门级选手,就简单的说一下RadioGroup组中RadioButton的布局和初始化 ...

  4. 访问不了虚拟机 ubuntu中的myql,解决方案

    ============================================================== 1. 现象 2. 原因分析 2.1 访问虚拟机中的mysql的前提: 你的 ...

  5. .net Core 2.0应用程序发布到IIS上注意事项

    .net Core2.0应用程序发布window服务器报错容易错过的配置. 1.应用程序发布. 2.IIS上新建网站. 3.应用程序池选择无托管代码. 4.服务器上安装DotNetCore.1.0.1 ...

  6. URL跳转与webview安全浅谈

    URL跳转与webview安全浅谈 我博客的两篇文章拼接在一起所以可能看起来有些乱 起因 在一次测试中我用burpsuite搜索了关键词url找到了某处url我测试了一下发现waf拦截了指向外域的请求 ...

  7. [Java]LeetCode133. 克隆图 | Clone Graph

    Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's ...

  8. [Swift]LeetCode522. 最长特殊序列 II | Longest Uncommon Subsequence II

    Given a list of strings, you need to find the longest uncommon subsequence among them. The longest u ...

  9. 并发编程(三)—— ReentrantLock的用法

    ReentrantLock是Java并发包中提供的一个可重入的互斥锁.ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性.只不过相比原生的Sync ...

  10. asp.net core 系列 2 启动Startup类介绍

    一.Startup类 ASP.NET Core 应用是一个控制台应用,它在其 Program.Main 方法中创建 Web 服务器.其中Main方法是应用的托管入口点,Main 方法调用 WebHos ...