•她的第一次

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

  那晚,我们......

  记得第一次接触这个 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. Design Patterns All in One (JavaScript Version)

    Design Patterns All in One (JavaScript Version) JavaScript 设计模式 JavaScript 数据结构 23种设计模式分为 3 大类: 创建型模 ...

  2. how to input special symbol in macOS

    how to input special symbol in macOS 如何在 macOS 中输入特殊符号 1024 ≈ 1000 2^10 == 1024 约等于 1000, 方便用来表示 Opt ...

  3. swiper & swiper slider

    swiper & swiper slider mobile swiper https://idangero.us/swiper/ https://idangero.us/swiper/get- ...

  4. 千万不要错过VAST,NGK算力的下一个财富机会!

    我们把目光投向NGK市场,近来,NGK接连新币,推出了SPC后,又有VAST.在目前市场上债券收益率已经趋近于零的情况下,世界上的大多数央行都在试图让本国货币贬值,所以在此时寻找其他保值资产是合理的. ...

  5. 20201228 买卖股票的最佳时机 IV(困难)

    给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意:你不能同时参 ...

  6. Nifi组件脚本开发—ExecuteScript 使用指南(二)

    Part 2 - FlowFile I/O 和 Error Handling flow File的IO NiFi 的 Flow files 由两个主要部件组成:attributes 和 content ...

  7. 页面强制重新加载js的办法

    1:线上强制重新加载js的办法 js后缀?v1.0 2:开发环境强制重新加载js的办法?now=Date.now() 3:开发环境强制重新加载js的办法F12进入调试页面选择network下单 dis ...

  8. nacos服务注册与发现之客户端

    服务注册 1.1 NamingService.registerInstance的方法为客户端提供的服务注册接口 1.2 客户端通过调用NamingService.registerService上报到n ...

  9. c++函数指针说明

    下面随笔说明函数指针用法. 函数指针的定义: 定义形式: 存储类型 数据类型 (*函数指针名)() 含义: 函数指针指向的是程序代码存储区 函数指针的典型用途-----实现函数回调 通过函数指针调用的 ...

  10. 微信小程序弹出框滚动穿透问题

    1.在你的遮罩层最外层加 catchtouchmove="noneEnoughPeople" 里面是你的方法名2.noneEnoughPeople: function () { c ...