•她的第一次

  话说,那是一个风雪交加的夜晚,看着她独自一个人走在漆黑的小道上,我抓紧跟了过去;

  那晚,我们......

  记得第一次接触这个 Layoutinflater 应该是在学习 ListView 的时候;

  在为 ListView 添加适配器 Adapter 的时候,会用到这个;

  当时也是大致了解了一下它的作用,今天有空,就让我们来深入了解一下;

•她知他长短

Layoutinflater与findViewById的恩怨情仇

  LayoutInflater 是用来找 layout 下  .xml 布局文件,并且实例化;

  而findViewById()是找具体  .xml  下的具体 widget控件:

  • Button mBtn = findViewById(R.id.btn);
  • TextView mTv = findViewById(R.id.tv);
  • ......

  对于一个没有被载入或者想要动态加载的界面,都需要使用 LayoutInflater.inflate() 来载入。

  什么叫做动态加载的界面呢?

动态加载界面

  修改 activity_main.xml 中的代码;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="动态添加子布局"
android:textSize="30sp"
/>
<LinearLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:orientation="vertical"> </LinearLayout>
</LinearLayout>

  在该布局中,天机了一个 <TextView> 用于显示一行文字;

  并添加了一个  android:id 为 layout 的 <LinearLayout>,该 LinearLayout 中未添加任何控件;

  接下来我们就尝试动态向该 LinearLayout 中添加控件;

  在 layout 下新建一个子布局文件 layout_item.xml,并添加如下代码;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp"
android:orientation="vertical"
android:gravity="center"> <View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/black"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/green"/> </LinearLayout>

  该布局也是非常的简单,就是两块涂满颜色的 <View>;

  修改 MainActivity.java 中的代码,将该布局添加到 layout 中;

public class MainActivity extends AppCompatActivity {

    private LinearLayout mLinearLayout;//对应于主布局中用来添加子布局的View
private View mView;// 子Layout要以view的形式加入到主Layout
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mLinearLayout = findViewById(R.id.layout);
mLinearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mView = View.inflate(MainActivity.this,R.layout.layout_item,null);
if(v.getId() == R.id.layout){
mLinearLayout.addView(mView);
}
}
});
}
}

  分析一下该代码:

  • 首先,通过 findViewById() 找到 layout
  • 接着,为 layout 设置点击事件
  • 在该点击事件中,通过 View 的  inflate() 方法动态加载 layout_item 布局
  • 最后,通过  addView() 方法将 layout_item 加载到 layout 中

  让我们来看看运行效果:

  是不是添加成功了?

  不知道你有没有发现一个问题,在 layout_item.xml 中设置的 layout_width 和 layout_height 都是 200dp;

  为什么在 layout 中显示的是 match_parent 呢?

  欲知后事如何,请听下回分解。

•他知她深浅

  休息是不可能休息的,接着上课;

参数类型

  接下来看一下 LayoutInflater 中的 inflate() 的用法;

  该方法接收三个参数(int resource, ViewGroup root, boolean attachToRoot):

  • resource:需要加载布局文件的 id

    • 意思是需要将这个布局文件中加载到Activity中来操作。
  • root:需要附加到 resource 资源文件的根控件

    • 什么意思呢,就是  inflate()  方法会返回一个 View 对象
    • 如果第三个参数 attachToRoot 为 true,就将这个 root 作为根对象返回
    • 否则仅仅将这个root对象的 LayoutParams 属性附加到 resource 对象的根布局对象上
    • 也就是布局文件 resource 的最外层的 View 上
  • attachToRoot:是否将root附加到布局文件的根视图上

编写代码

  下面,我们通过代码来直观感受一下;

  修改 activity_main.xml 中的代码;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> </LinearLayout>

  对这个布局是不是很眼熟;

  同样,为 <LinearLayout> 设置了  android:id 属性;

  接下来我们还是动态向该 <LinearLayout> 中添加布局,就用上面的 layout_item 布局吧;

  修改 MainActivity.java 中的代码;

public class MainActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); LinearLayout ll = findViewById(R.id.main_layout);
LayoutInflater inflater = LayoutInflater.from(MainActivity.this); View view = inflater.inflate(R.layout.layout_item, ll,true);
}
}

   inflate()  方法返回的是一个 View,而我并没有添加这个返回的 View;

  为什么就已经将 layout_item 添加进来了呢?

  因为我的第三个参数设置为 true,表示将第一个参数所指定的布局添加到第二个参数的 View 中。

运行结果

  

  有没有发现,layout_item.xml 中的 layout_weight 和 layout_height 生效了?

踩坑

  如果我们在最后额外添加  ll.addView(view); ,运行的时候将会报错;

  意思大概是重复添加子项布局;

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

设置attachToRoot为false

  下面我们再来看看当第三个参数 attachToRoot 为 false 时的情况;

  当 attachToRoot 为 false 时,表示不将第一个参数所指定的 View 添加到第二个参数 root 中去。

  因为我们想要添加布局可以把第三个参数设为 true,那我们为什么这里要设为 false 呢?

  我们在设置控件的时候,都会设置 layout_width 和 layout_height,这两个属性表示的是在容器里的大小;

  当然也意味着,这两个属性必须要在容器里才有意义,否则没有意义。

  这就意味着如果我直接将 layout_item 加载进来而不给它指定一个父布局;

  则 inflate 布局的根节点的 layout_width 和 layout_height 属性将会失效;

  还是通过代码来直观感受,修改 MainActivity.java 中的代码;

public class MainActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); LinearLayout ll = findViewById(R.id.main_layout);
LayoutInflater inflater = LayoutInflater.from(MainActivity.this); // 重复添加布局,报错
// View view = inflater.inflate(R.layout.layout_item, ll,true);
// ll.addView(view); //layout_item 中的 layout_width和layout_height属性将会失效
View view = inflater.inflate(R.layout.layout_item,null);
ll.addView(view);
}
}

运行结果

  

  是不是失效了?

设置attachToRoot为false并添加root

  如果我想让 layout_item 的根节点有效,又不想让其处于某一个容器中;

  那我就可以设置 root 不为 null,而 attachToRoot 为 false。

  接着修改 MainActivity.java 中的代码;

public class MainActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); LinearLayout ll = findViewById(R.id.main_layout);
LayoutInflater inflater = LayoutInflater.from(MainActivity.this); // 重复添加布局,报错
// View view = inflater.inflate(R.layout.layout_item, ll,true);
// ll.addView(view); //layout_item 中的 layout_width和layout_height属性将会失效
// View view = inflater.inflate(R.layout.layout_item,null);
// ll.addView(view); View view = inflater.inflate(R.layout.layout_item,ll,false);
ll.addView(view);
}
}

运行结果

  

Android学习之Layoutinflater的用法的更多相关文章

  1. android学习9——Handler简单用法

    Handler用来发消息和处理消息.典型的用法是更新界面.android不允许在子线程里面更新界面,通常是把Handler传到子线程中,在子线程里通过sendEmptyMessage函数发消息.Han ...

  2. [Android学习笔记]LayoutInflater的使用

    LayoutInflater用于动态载入布局,然后获取到布局中定义完成的控件引用 常在动态加载布局,和Adapter中用到 使用步骤:1.通过LayoutInflater加载xml布局文件2.从载入的 ...

  3. Android学习笔记_72_Spinner的用法

    一.普通 1. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android= ...

  4. 十、Android学习第九天——小结(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 十.Android学习第九天——小结 通过这段时间的学习,今晚上来做个小小 ...

  5. Android学习第三天-打包常用命令

    在前面<Android学习第一天-adb常用命令>和 <Android学习第二天-android常用命令>两篇博文中,我们重点讲解了adb和android的常用命令,下面我们讲 ...

  6. 【Android学习】《Android开发视频教程》第一季笔记

    视频地址: http://study.163.com/course/courseMain.htm?courseId=207001 课时5    Activity基础概念 1.Android开发技术结构 ...

  7. Android学习随笔--ListView的分页功能

    第一次写博客,可能格式,排版什么的会非常不美观,不过我主要是为了记录自己的Android学习之路,为了以后能有些东西回顾.既然是为了学习,那我肯定会吸收各位大大们的知道经验,有不足的地方请指出. 通过 ...

  8. android学习日记03--常用控件Dialog

    常用控件 9.Dialog 我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框 对话框,要创建对话框之前首先要创建Bui ...

  9. android学习日记03--常用控件checkbox/radiobutton

    常用控件3.checkbox 复选框,确定是否勾选,点击一下勾选,点击第二下取消,当有一系列备选项时适合用checkbox控件,方便用户提交数据. 贴上例子Activity的java代码 packag ...

随机推荐

  1. SQL All In One

    SQL All In One Structured Query Language SQL is an ANSI (American National Standards Institute) stan ...

  2. Github history viewer

    Github history viewer https://github.githistory.xyz/ https://github.com/pomber/git-history https://c ...

  3. Dart DevTools & Flutter

    Dart DevTools & Flutter https://flutter.dev/docs/development/tools/devtools/overview https://dar ...

  4. npm & cli & cp: no such file or directory

    npm & cli & cp: no such file or directory empty files bug https://npm.runkit.com/hui-cli htt ...

  5. taro list render bug

    taro list render bug 列表渲染 https://taro-docs.jd.com/taro/docs/list.html not support jsx map 垃圾微信 cons ...

  6. nasm astrcmp函数 x86

    xxx.asm: %define p1 ebp+8 %define p2 ebp+12 %define p3 ebp+16 section .text global dllmain export as ...

  7. C++算法代码——骨牌铺法

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1638 题目描述 输入 输入一个正整数,表示n. 输出 输出一个正整数,表示铺法. 样 ...

  8. C#使用OpenCV剪切图形中的人物头像

    前言 本文主要介绍如何使用OpenCV剪切图形中的人物头像. 准备工作 首先创建一个Wpf项目--OpenCV_Face_Wpf,这里版本使用Framework4.7.2. 然后使用Nuget搜索[E ...

  9. spring-ioc的注解 理解-1

    简单对象注入的理解 用到了两个对象 Student .Wife ,一个xml配置(在idea编译器的resource文件下),主要是为让spring去扫描注解,一个测试类,一个pom.xml,导入需要 ...

  10. 一次 MySQL 线上死锁分析实战

    关键词:MySQL Index Merge 前言 MySQL 的锁机制相信大家在学习 MySQL 的时候都有简单的了解过,那既然有锁就必定绕不开死锁这个问题.其实 MySQL 在大部分场景下是不会存在 ...