Android LayoutInflater 深度解析

在这里插入图片描述

在 Android 开发中,LayoutInflater 是一个非常重要的工具。它允许我们从 XML 布局文件中动态地创建 View 对象,从而使得 UI 的创建和管理更加灵活。本文将深入解析 android.view.LayoutInflater,包括它的基本用法、常见问题以及高级用法。

什么是 LayoutInflater?

LayoutInflater 是 Android 提供的一个类,用于将 XML 布局文件解析成对应的 View 对象。它通常用于 Activity 和 Fragment 中,通过代码动态地创建和操作 UI 元素。

基本用法

LayoutInflater 的基本用法非常简单,通常有以下几种方式:

从 Activity 获取 LayoutInflater

val inflater = LayoutInflater.from(this)
// 或者
val inflater = this.layoutInflater

从 Context 获取 LayoutInflater

val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

从 Fragment 获取 LayoutInflater

val inflater = requireActivity().layoutInflater

常见用法示例

在 Activity 中使用 LayoutInflater

在 Activity 中,我们可以使用 LayoutInflater 来动态地加载布局,例如在一个 LinearLayout 中添加多个子视图:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val container = findViewById<LinearLayout>(R.id.container)
        val inflater = LayoutInflater.from(this)

        val itemView = inflater.inflate(R.layout.item_layout, container, false)
        container.addView(itemView)
    }
}

在 Fragment 中使用 LayoutInflater

在 Fragment 中,我们通常在 onCreateView 方法中使用 LayoutInflater 来加载布局:

class MyFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_layout, container, false)
        // 初始化视图
        return view
    }
}

LayoutInflater 的高级用法

除了基本的用法,LayoutInflater 还有一些高级用法和技巧,可以帮助我们更高效地创建和管理视图。

视图缓存

在性能敏感的应用中,频繁地调用 LayoutInflater.inflate 可能会导致性能问题。为了提高性能,我们可以缓存已经加载的视图:

class MainActivity : AppCompatActivity() {
    private lateinit var cachedView: View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val container = findViewById<LinearLayout>(R.id.container)
        val inflater = LayoutInflater.from(this)

        // 缓存视图
        if (!::cachedView.isInitialized) {
            cachedView = inflater.inflate(R.layout.item_layout, container, false)
        }

        container.addView(cachedView)
    }
}

自定义 LayoutInflater.Factory

我们可以通过实现 LayoutInflater.Factory 接口来自定义视图创建逻辑。例如,我们可以在视图创建时自动应用自定义字体:

class CustomFontFactory : LayoutInflater.Factory {
    override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
        val view = LayoutInflater.from(context).createView(name, null, attrs)
        if (view is TextView) {
            view.typeface = Typeface.createFromAsset(context.assets, "custom_font.ttf")
        }
        return view
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val inflater = LayoutInflater.from(this)
        inflater.factory = CustomFontFactory()

        setContentView(R.layout.activity_main)
    }
}

常见问题和解决方案

inflate 方法的第三个参数 attachToRoot

LayoutInflater.inflate 方法的第三个参数 attachToRoot 经常会让人困惑。这个参数决定了新创建的视图是否应该被立即添加到传入的根视图中:

  • 如果 attachToRoottrue,新创建的视图会被立即添加到根视图中,且 inflate 方法会返回根视图。
  • 如果 attachToRootfalse,新创建的视图不会被添加到根视图中,且 inflate 方法会返回新创建的视图。

示例:

val container = findViewById<LinearLayout>(R.id.container)

// attachToRoot = true
val view1 = LayoutInflater.from(this).inflate(R.layout.item_layout, container, true)
// view1 == container

// attachToRoot = false
val view2 = LayoutInflater.from(this).inflate(R.layout.item_layout, container, false)
// view2 != container

自定义 View 和自定义属性

在使用 LayoutInflater 加载自定义 View 时,我们需要确保自定义属性可以正确应用。这通常通过在自定义 View 的构造函数中读取属性来实现:

class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    init {
        context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.CustomView,
            0, 0).apply {
            try {
                val customAttribute = getString(R.styleable.CustomView_customAttribute)
                // 使用自定义属性
            } finally {
                recycle()
            }
        }
    }
}

在 XML 中使用自定义 View 和属性:

<com.example.CustomView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:customAttribute="Hello, Custom!" />

结论

LayoutInflater 是 Android 开发中不可或缺的工具,通过理解和掌握它的用法,可以大大提高 UI 开发的效率和灵活性。无论是基本的布局加载,还是高级的自定义视图创建,LayoutInflater 都提供了强大的功能和灵活性。希望本文能帮助你更好地理解和使用 LayoutInflater,提升你的安卓开发技能。

Best regards!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

stm32学习笔记---DMA直接存储器存取(代码部分)DMA数据转运/DMA+AD多通道

目录 第一个代码&#xff1a;DMA数据转运 扩展知识 DMA的配置步骤 DMA的库函数 DMA_DeInit DMA初始化和DMA结构体初始化函数 DMA_Cmd DMA_ITConfig DMA_SetCurrDataCounter DMA_GetCurrDataCounter 四个获取标志位状态函数 代码实现 MyDMA.c 第一步&#xff0c;开…

网站提示不安全怎么办

当您访问一个网站时&#xff0c;如果浏览器提示该网站不安全&#xff0c;这通常意味着以下几个问题之一&#xff0c;以及相应的解决办法&#xff1a; 一、未启用HTTPS协议&#xff1a; 解决方法&#xff1a;确保网站启用了HTTPS协议。这意味着您需要为您的网站部署一个有效的…

鸿蒙:this传递参数到子组件中无法实现

this指代当前组件的某个变量&#xff0c;当把这个变量当作参数传递给子组件时&#xff0c;子组件中没有这个变量&#xff0c;属于使用不了这个变量 解决方法&#xff1a;在变量后面加.bind(this)将当前组件的变量一起绑定过去

电脑ip地址在哪里看?3个方法全解析,找到地址不迷路

ip地址&#xff0c;就像网络世界中的身份证&#xff0c;是每个设备在网络上的唯一标识。无论是浏览网页、在线聊天还是远程办公&#xff0c;都离不开它的指引。那么&#xff0c;电脑ip地址在哪里看&#xff1f;别担心&#xff0c;本文将带你踏上寻找ip地址的冒险之旅&#xff0…

#HDC2024 心得分享#主题演讲学习-加入鸿蒙生态正当时

一、主题演讲学习心得 通过本次主题演讲的聆听与学习&#xff0c;我们在猜出中和不太确定的相关内容纷纷呈现。比如鸿蒙内核与HarmonyOS Next获得行业内最高等级的安全认证&#xff1b;盘古大模型、小艺智能体、意图理解与分发框架等构筑的AI、AIGC能力对HarmonyOS Next及原生…

ABeam×StartUp | ABeam德硕中国新创部门拜访通用机器人初创公司 :逐际动力,就具身智能机器人的发展展开交流

近日&#xff0c;ABeam中国新创部门有幸拜访了深圳逐际动力科技有限公司&#xff08;以下简称&#xff1a;逐际动力&#xff09;。作为一家通用机器人公司&#xff0c;其在人形机器人、四轮足机器人等领域具有深厚的学术与技术储备。 现场合影 左&#xff1a;ABeam中国新创部门…

Golang | Leetcode Golang题解之第202题快乐数

题目&#xff1a; 题解&#xff1a; func isHappy(n int) bool {cycle : map[int]bool{4: true, 6: true, 37: true, 58: true, 89: true, 145: true, 42: true, 20: true}for n ! 1 && !cycle[n] {n step(n)}return n 1 }func step(n int) int {sum : 0for n > …

交友系统定制版源码| 相亲交友小程序源码全开源可二开_打造独特的社交交友系统

交友系统源码的实现涉及到多个方面&#xff0c;包括前端页面设计、后端逻辑处理、数据库设计以及用户交互等。以下是一个简单的交友系统源码实现的基本框架和关键步骤: 1.数据库设计:用户表:存储用户基本信息&#xff0c;如用户ID、用户名、密码、头像、性别、年龄、地理位置等…

无人机的起源

无人机起源于20世纪初的早期实验阶段&#xff0c;并随着技术进步逐步发展。无人机&#xff0c;作为现代科技领域中的一项重要创新&#xff0c;已经在全球范围内展现出其巨大的潜力和应用价值。 无人机的历史可以追溯到1917年&#xff0c;美国人艾德温.奥斯特林发明了“飞行训练…

Spring企业开发核心框架-下

五、Spring AOP面向切面编程 1、场景设定和问题复现 ①准备AOP项目 项目名&#xff1a;Spring-aop-annotation ②声明接口 /*** - * / 运算的标准接口!*/ public interface Calculator { int add(int i, int j); int sub(int i, int j); int mul(int i, in…

每日一题——Python实现PAT乙级1096 大美数(举一反三+思想解读+逐步优化)3千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度分析 空间复杂度分析 总结 哲学和编程思想 1. 抽象与具体化 …

svn切换分支

现在有一个场景&#xff1a; 在svn中有一个b分支&#xff0c;是基于a分支拉出来的&#xff0c;并且我的b分支在本地已经有了改动&#xff0c;a分支在远端也有了改动&#xff0c; 我想把远端a分支的改动同步到我的本地b分支上&#xff0c;如何操作 目前已知的方法 项目右键-&g…

动手学深度学习(Pytorch版)代码实践 -计算机视觉-49风格迁移

49风格迁移 读入内容图像&#xff1a; import torch import torchvision from torch import nn import matplotlib.pylab as plt import liliPytorch as lp from d2l import torch as d2l# 读取内容图像 content_img d2l.Image.open(../limuPytorch/images/rainier.jpg) plt.…

J019_选择排序

一、排序算法 排序过程和排序原理如下图所示&#xff1a; 二、代码实现 package com.itheima.sort;import java.util.Arrays;public class SelectSort {public static void main(String[] args) {int[] arr {5, 4, 3, 1, 2};//选择排序for (int i 0; i < arr.length - 1…

django西餐厅管理系统-计算机毕业设计源码10873

摘要 在现代餐饮行业中&#xff0c;高效的管理系统对于西餐厅的成功运营至关重要。为了满足西餐厅日益增长的管理需求&#xff0c;设计并实现了一款基于 Python 的西餐厅管理系统。 Python作为一种简洁而易读的编程语言&#xff0c;具有广泛的应用领域&#xff0c;包括Web开发。…

MySQL5.7安装初始化错误解决方案

问题背景 今天在给公司配数据库环境时,第一次报initializing database 数据库初始化错误? 起初没管以为是安装软件原因,然后就出现以下错误:如下图 点开log,我们观察日志会发现 无法识别的参数 ‘mysqlx_port=0.0’,???,官方的安装程序还能出这问题?

docker的安装与基本使用

一.docker的安装卸载 1.先安装所需软件包 yum install -y yum-utils2.设置stable镜像仓库 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 3.安装DOCKER CE yum -y install docker-ce docker-ce-cli containerd.io 4.验…

【SpringCloud】Eureka源码解析 上

Eureka是一个服务发现与注册组件&#xff0c;它包含服务端和客户端&#xff0c;服务端管理服务的注册信息&#xff0c;客户端简化服务实例与服务端的交互。我们结合源码来分析下eureka组件的实现原理&#xff0c;内容分为上下两章&#xff0c;第一章分析eureka的服务注册&#…

【每日一练】python if选择判断结构应用

应用类 1. 计算面积 编写一个Python程序&#xff0c;计算矩形的面积。要求用户输入矩形的宽和高&#xff0c;然后计算并打印面积。 width float(input("请输入矩形的宽&#xff1a;")) height float(input("请输入矩形的高&#xff1a;")) if width &…

《数字图像处理与机器视觉》案例三 (基于数字图像处理的物料堆积角快速测量)

一、前言 物料堆积角是反映物料特性的重要参数&#xff0c;传统的测量方法将物料自然堆积&#xff0c;测量物料形成的圆锥表面与水平面的夹角即可&#xff0c;该方法检测效率低。随着数字成像设备的推广和应用&#xff0c;应用数字图像处理可以更准确更迅速地进行堆积角测量。 …