Android View.inflate 和 LayoutInflater.from(this).inflate 的区别

news2024/11/26 2:40:54

前言

两个都是布局加载器,而View.inflate是对 LayoutInflater.from(context).inflate的封装,功能相同,案例使用了dataBinding。

View.inflate(context, layoutResId, root)

LayoutInflater.from(context).inflate(layoutResId, root, false)

区别

因为View.inflate(context,layoutResId,root)  LayoutInflater.from(context).inflate(layoutResId, root, attachToRoot) 少了一个attachToRoot参数(是否将layoutResId添加到某个View中,作为其子View)。

在使用View.inflate(context,layoutResId,root) 时,如果root(父View)是null,会导致layoutResId布局中声明的宽高 + 外边距参数,失效。

核心条件就是root(父View)是不是null。

案例

1、使用View.inflate(context,layoutResId,root) root不为null

    private AppActivityMainBinding bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = AppActivityMainBinding.bind(getLayoutInflater().inflate(R.layout.app_activity_main,null));        
        setContentView(bind.getRoot());

        // 子布局:R.layout.app_layout_text    
        // 父布局:bind.box
        View.inflate(this,R.layout.app_layout_text,bind.box);
        View.inflate(this,R.layout.app_layout_text,bind.box);
        View.inflate(this,R.layout.app_layout_text,bind.box);

    }

2、使用LayoutInflater.from(context).inflate(layoutResId, root, attachToRoot)  root不为null,且attachToRoot是true

    private AppActivityMainBinding bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = AppActivityMainBinding.bind(getLayoutInflater().inflate(R.layout.app_activity_main,null));        
        setContentView(bind.getRoot());

        // 子布局:R.layout.app_layout_text    
        // 父布局:bind.box
        LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);
        LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);
        LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);

    }

两种方式效果相同,宽高 + 外边距 都有效

3、使用View.inflate(context,layoutResId,root) root为 null

    private AppActivityMainBinding bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = AppActivityMainBinding.bind(getLayoutInflater().inflate(R.layout.app_activity_main,null));        
        setContentView(bind.getRoot());

        // 子布局:R.layout.app_layout_text    
        // 父布局:bind.box
        View view = View.inflate(this, R.layout.app_layout_text, null);
        View view2 = View.inflate(this, R.layout.app_layout_text, null);
        View view3 = View.inflate(this, R.layout.app_layout_text, null);
        bind.box.addView(view);
        bind.box.addView(view2);
        bind.box.addView(view3);
    }

4、使用LayoutInflater.from(context).inflate(layoutResId, root, attachToRoot)  root为 null,且attachToRoot是false

    private AppActivityMainBinding bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = AppActivityMainBinding.bind(getLayoutInflater().inflate(R.layout.app_activity_main,null));        
        setContentView(bind.getRoot());

        // 子布局:R.layout.app_layout_text    
        // 父布局:bind.box
        View view = LayoutInflater.from(this).inflate(R.layout.app_layout_text, null, false);
        View view2 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, null, false);
        View view3 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, null, false);
        bind.box.addView(view);
        bind.box.addView(view2);
        bind.box.addView(view3);
    }

两种方式效果相同,宽高 + 外边距 都失效了,宽/高 变成wrap_content一点要记住这点!!!是变成wrap_content

至于为什么layoutResId布局宽度和父View一样,当子View失去自身LayoutParams(布局参数)后,父View会自动调整子View的宽高属性,下面会讲先忽略

5、如果不想将layoutResId布局添加到父View中,同时又不想丢失layoutResId布局中声明的参数,LayoutInflater.from(context).inflate(layoutResId, root, attachToRoot)这样写可以做到,root不为null,但是attachToRootfalse

    private AppActivityMainBinding bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = AppActivityMainBinding.bind(getLayoutInflater().inflate(R.layout.app_activity_main,null));        
        setContentView(bind.getRoot());

        // 子布局:R.layout.app_layout_text    
        // 父布局:bind.box
        View view = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);
        View view2 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);
        View view3 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);
        bind.box.addView(view);
        bind.box.addView(view2);
        bind.box.addView(view3);
    }

效果

6、而View.inflate(context,layoutResId,root) 目前为止无法做到,因为它少了一个attachToRoot参数(是否将layoutResId添加到某个View中,作为其子View),以后说不准会有这个参数的重载方法。

7、案例文件:shape_border.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke android:color="@color/color_303133" android:width="1dp"/>
</shape>

8、案例文件:app_layout_text.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="200dp"
    android:layout_marginBottom="20dp"
    android:background="@drawable/shape_border"
    android:paddingLeft="20dp"
    android:paddingTop="50dp"
    android:text="测试" />

9、案例文件:app_activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <LinearLayout
        android:id="@+id/box"
        android:orientation="vertical"
        android:background="@color/color_14F9230A"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </LinearLayout>

</layout>

10、案例文件:AppMainActivity.Java

public class AppMainActivity extends AppCompatActivity {

    private AppActivityMainBinding bind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = AppActivityMainBinding.bind(getLayoutInflater().inflate(R.layout.app_activity_main,null));
        setContentView(bind.getRoot());

        // View.inflate(this,R.layout.app_layout_text,bind.box);
        // View.inflate(this,R.layout.app_layout_text,bind.box);
        // View.inflate(this,R.layout.app_layout_text,bind.box);

        // View view = View.inflate(this, R.layout.app_layout_text, null);
        // View view2 = View.inflate(this, R.layout.app_layout_text, null);
        // View view3 = View.inflate(this, R.layout.app_layout_text, null);
        // bind.box.addView(view);
        // bind.box.addView(view2);
        // bind.box.addView(view3);


        // LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);
        // LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);
        // LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);

        // View view = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);
        // View view2 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);
        // View view3 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);
        // bind.box.addView(view);
        // bind.box.addView(view2);
        // bind.box.addView(view3);

        // View view = LayoutInflater.from(this).inflate(R.layout.app_layout_text, null, false);
        // View view2 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, null, false);
        // View view3 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, null, false);
        // bind.box.addView(view);
        // bind.box.addView(view2);
        // bind.box.addView(view3);

}

源码解析

View.inflate源码,还是调用的LayoutInflater.from(context).inflate

    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
        LayoutInflater factory = LayoutInflater.from(context);
        return factory.inflate(resource, root);
    }

LayoutInflater.java源码

第一判断条件是root(父布局)是否为null,第二判断条件就是attachToRoot,View.inflate没有这个参数。

    ... ... 

    View result = root;

    ... ... 

    if (root != null) {
        // Create layout params that match root, if supplied
        params = root.generateLayoutParams(attrs);
        if (!attachToRoot) {
            // Set the layout params for temp if we are not
            // attaching. (If we are, we use addView, below)
            temp.setLayoutParams(params);
        }
    }

    ... ... 

    return result;

父View自动调整子View的宽高

当子View 失去或没有 自身LayoutParams(布局参数)后,父View会自动调整子View的宽高。

布局类型不同,子View宽高值也不同,说几个常用布局:

FrameLayout:宽 高 都会变成match_parent

RelativeLayout 和 ConstraintLayout 一样,宽 高 都会变成wrap_content

LinearLayout 设置vertical(垂直方向):变成match_parent变成wrap_content

LinearLayout 设置horizontal(水平方向):宽 / 高 都会变成wrap_content

总结

只有在实例化layoutResId布局时,而又不想 作为子View、不想丢失声明的参数,它俩才会有使用区别。

顺便说一下返回值layoutResId布局作为子View时,返回的是父布局View,反之返回的是layoutResId布局View,这一点它们是一样的。


         View view = View.inflate(this, R.layout.app_layout_text, bind.box);

         Log.d("TAG","父布局LinearLayout:"+(view instanceof LinearLayout)); // true
         Log.d("TAG","当前布局TextView:"+(view instanceof TextView)); // false

         View view2 = View.inflate(this, R.layout.app_layout_text, null);

         Log.d("TAG","父布局LinearLayout:"+(view2 instanceof LinearLayout)); // false
         Log.d("TAG","当前布局TextView:"+(view2 instanceof TextView)); // true




         View view3 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, true);

         Log.d("TAG", "父布局LinearLayout:" + (view3 instanceof LinearLayout)); // true
         Log.d("TAG", "当前布局TextView:" + (view3 instanceof TextView)); // false

         View view4 = LayoutInflater.from(this).inflate(R.layout.app_layout_text, bind.box, false);

         Log.d("TAG", "父布局LinearLayout:" + (view4 instanceof LinearLayout)); // false
         Log.d("TAG", "当前布局TextView:" + (view4 instanceof TextView)); // true


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能原理复习--搜索策略(一)

文章目录 上一篇搜索概述一般图搜索盲目搜索下一篇 上一篇 人工智能原理复习–确定性推理 搜索概述 问题求解分为两大类&#xff1a;知识贫乏系统&#xff08;依靠搜索技术解决&#xff09;、知识丰富系统&#xff08;依靠推理技术&#xff09; 两大类搜索技术&#xff1a; …

实验3.5 路由器的单臂路由配置

实验3.5 路由器的单臂路由配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.SWA的基本配置2.RA的基本配置3.在RA上查看接口状态 六、任务验收七、任务小结 一、任务描述 某公司对部门划分了需VLAN之后&#xff0c;发现两个部门之间无法通信&#xff0c;但…

深入理解 Promise:前端异步编程的核心概念

深入理解 Promise&#xff1a;前端异步编程的核心概念 本文将帮助您深入理解 Promise&#xff0c;这是前端异步编程的核心概念。通过详细介绍 Promise 的工作原理、常见用法和实际示例&#xff0c;您将学会如何优雅地处理异步操作&#xff0c;并解决回调地狱问题。 异步编程和…

从阻抗匹配看拥塞控制

先来理解阻抗匹配&#xff0c;但我不按传统方式解释&#xff0c;因为传统方案你要先理解如何定义阻抗&#xff0c;然后再学习什么是输入阻抗和输出阻抗&#xff0c;最后再看如何让它们匹配&#xff0c;而让它们匹配的目标仅仅是信号不反射&#xff0c;以最大能效被负载接收。 …

【二分查找】LeetCode:2354.优质数对的数目

作者推荐 贪心算法LeetCode2071:你可以安排的最多任务数目 本文涉及的基础知识点 二分查找算法合集 题目 给你一个下标从 0 开始的正整数数组 nums 和一个正整数 k 。 如果满足下述条件&#xff0c;则数对 (num1, num2) 是 优质数对 &#xff1a; num1 和 num2 都 在数组 …

excel数据重复率怎么计算【保姆教程】

大家好&#xff0c;今天来聊聊excel数据重复率怎么计算&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; excel数据重复率怎么计算 在Excel中计算数据重复率可以通过以下步骤实现&#xff1a; 1. 确定重复…

初识Matter——esp-box控制两盏灯

初识Matter 一、效果展示 二、准备 1.ubuntu系统/Mac系统电脑 2.安装esp-idf及esp-matter环境 3.esp-box设备 4.两块esp32 5.两个led灯或使用板载灯 三、烧录固件&#xff08;esp-box&#xff09; 下载esp-box例程 git地址&#xff1a;GitHub - espressif/esp-box: Th…

基于单片机指纹考勤机控制系统设计

**单片机设计介绍&#xff0c;基于单片机指纹考勤机控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的指纹考勤机控制系统是一种用于管理员工考勤和实现门禁控制的设计方案。它通过使用单片机作为主控制器…

线性代数入门与学习笔记

该内容为重拾部分线性代数知识的学习笔记&#xff0c;内容上更多的是为了解决问题而学习的内容&#xff0c;并非系统化的学习。 针对的问题为&#xff1a;Music算法推导求解过程中的矩阵计算知识。 学习的内容包括&#xff1a;矩阵原理、矩阵行列式、矩阵的秩、线性变换矩阵变换…

J.408之数据结构

J-408之数据结构_北京信息科技大学第十五届程序设计竞赛&#xff08;同步赛&#xff09; (nowcoder.com) 思维好题&#xff0c;直接用两个set存没出现的数字就好了 // Problem: 408之数据结构 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/68572/J // Me…

cmake生成表达式

不积小流&#xff0c;无以成江海 <CONFIG:RELEASE> config这个关键字&#xff0c;主要是看CMAKE_BUILD_TYPE这个变量的值是不是和冒号后的一样&#xff0c;一样的话就返回true, 否则就是false. cmake_minimum_required(VERSION 3.10) project(Test) set(CMAKE_CXX_STA…

腾讯地图系列(二):微信小程序添加插件(三种方法)以及插件AppId获取

目录 第一章 前言 第二章 添加插件 2.1 微信小程序添加插件方法一&#xff08;微信公众平台添加插件&#xff09; 2.2 微信小程序添加插件方法二&#xff08;通过项目配置添加插件&#xff09; 2.3 微信小程序添加插件方法三&#xff08;微信公众平台服务市场添加插件&…

OpenCL学习笔记(一)开发环境搭建(win10+vs2019)

前言 异构编程开发&#xff0c;在高性能编程中有重要的&#xff0c;笔者本次只简单介绍下&#xff0c;如何搭建简单的开发环境&#xff0c;可以供有需要的小伙伴们开发测试使用 一、获取opencl的sdk库 1.使用cuda库 若本机有Nvidia的显卡&#xff0c;在安装cuda库后&#x…

理解 GET、POST、PATCH 和 DELETE 请求的参数传递方式

理解 GET、POST、PATCH 和 DELETE 请求的参数传递方式 本文将向您介绍在使用 GET、POST、PATCH 和 DELETE 请求时如何传递参数。通过详细解释每种请求的参数传递方式和示例代码&#xff0c;您将了解如何正确地将数据发送到服务器并与之交互。 GET 请求的参数传递方式 在 GET…

Navicat 技术指引 | 适用于 GaussDB 分布式的数据生成功能

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

spring boot学习第五篇:spring boot与JPA结合

1、准备表&#xff0c;创建表语句如下 CREATE TABLE girl (id int(11) NOT NULL AUTO_INCREMENT,cup_Size varchar(100) COLLATE utf8mb4_bin DEFAULT NULL,age int(11) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT4 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4…

JVS低代码表单引擎:数据校验与处理的先锋

随着信息技术的迅速发展&#xff0c;数据校验与处理已经成为了各类应用中不可或缺的一环。尤其是在涉及敏感信息&#xff0c;如密码处理时&#xff0c;其安全性和准确性显得尤为重要。JVS低代码表单引擎提供了强大的文本组件触发逻辑校验功能&#xff0c;它能够在用户填写数据的…

[笔记]ARMv7/ARMv8 交叉编译器下载

开发 Cortex-A7、Cortex-A72 或其他 ARM 架构 profile 芯片时&#xff0c;经常需要下载对应架构的交叉编译器&#xff0c;所以写这篇笔记&#xff0c;用于记录一下交叉编译器下载流程&#xff0c;免得搞忘。 编译环境&#xff1a;ubuntu 虚拟机 下载地址 我们可以从 ARM 官网…

二分查找|前缀和|滑动窗口|2302:统计得分小于 K 的子数组数目

作者推荐 贪心算法LeetCode2071:你可以安排的最多任务数目 本文涉及的基础知识点 二分查找算法合集 题目 一个数组的 分数 定义为数组之和 乘以 数组的长度。 比方说&#xff0c;[1, 2, 3, 4, 5] 的分数为 (1 2 3 4 5) * 5 75 。 给你一个正整数数组 nums 和一个整数…

教育心得整理

压抑使人反抗&#xff0c;反抗就是报复&#xff0c;报复就会引起犯罪。要消灭犯罪&#xff0c;我们必须杜绝引起孩子报复心理的行为&#xff0c;更重要的是&#xff0c;我们一定要对孩子表现出来爱与尊重 限制批评的次数限制每次批评的范围限制每次批评的强度 当彼此的信任和…