【Compose multiplatform教程20】在应用程序中使用多平台资源
为项目设置资源后,生成项目以生成提供资源访问权限的特殊类。要重新生成类和所有资源访问器,请再次生成项目或在 IDE 中重新导入项目。ResRes
之后,您可以使用生成的类从您的代码或外部库访问配置的多平台资源。
自定义访问器类生成
您可以使用 Gradle 设置自定义生成的类以满足您的需求。Res
在文件的块中,您可以指定多个设置,这些设置会影响为项目生成类的方式。示例配置如下所示:compose.resources {}build.gradle.ktsRes
compose.resources {publicResClass = falsepackageOfResClass = "me.sample.library.resources"generateResClass = auto
}
publicResClass设置为 将生成的类设为公共。默认情况下,生成的类是 internal。trueRes
packageOfResClass允许您将生成的类分配给特定的包(以便在代码中访问,以及在最终工件中进行隔离)。默认情况下,Compose Multiplatform 会将软件包分配给类。Res{group name}.{module name}.generated.resources
generateResClass设置为 使项目无条件生成类。当资源库仅可传递时,这可能很有用。默认情况下,仅当当前项目对资源库具有显式或依赖项时,Compose Multiplatform 才会使用该值来生成类。alwaysResautoResimplementationapi
资源使用情况
图像
您可以以简单图片、栅格化图片或 XML 矢量的形式访问可绘制资源。除 Android 之外的所有平台都支持 SVG 图像。
-
如需以图片形式访问可绘制对象资源,请使用以下函数:
PainterpainterResource()
@Composable
fun painterResource(resource: DrawableResource): Painter {...}
该函数采用资源路径并返回一个值。该函数在除 Web 之外的所有目标上同步工作。对于 Web 目标,它会为第一次合成返回一个空值,该合成将在后续合成中替换为加载的图像。painterResource() PainterPainter
painterResource()加载 a 用于栅格化图像格式,例如 、 、 、 或 用于 Android XML 矢量可绘制对象格式的 a。BitmapPainter.png.jpg.bmp.webpVectorPainterXML 矢量可绘制对象的格式与 Android 相同,只是它们不支持对 Android 资源的外部引用。
需以Bitmap图像的形式访问可绘制资源,请使用以下函数:ImageBitmap imageResource()
@Composable
fun imageResource(resource: DrawableResource): ImageBitmap {...}
如需以 XML 矢量的形式访问可绘制资源,请使用以下函数:ImageVector vectorResource()
@Composable
fun vectorResource(resource: DrawableResource): ImageVector {...}
以下示例说明了如何在 Compose Multiplatform 代码中访问图像:
Image(painter = painterResource(Res.drawable.my_icon),contentDescription = null
)
字符串
将所有字符串资源存储在目录中的 XML 文件中。将为每个文件中的每个项生成一个静态访问器。composeResources/values
简单字符串
要存储简单字符串,请在 XML 中添加一个元素:<string>
<resources><string name="app_name">My awesome app</string><string name="title">Some title</string>
</resources>
要将字符串资源作为 获取,请使用以下代码:String
From 可组合代码
@Composable
fun stringResource(resource: StringResource): String {...}@Composable
fun stringResource(resource: StringResource, vararg formatArgs: Any): String {...}
从不可组合代码
suspend fun getString(resource: StringResource): Stringsuspend fun getString(resource: StringResource, vararg formatArgs: Any): String
例如:
coroutineScope.launch {val appName = getString(Res.string.app_name)
}
您可以在字符串资源中使用特殊符号:
-
\n— 换行 -
\t— 对于 Tab 符号 -
\uXXXX— 对于特定的 Unicode 字符 -
字符串模板
目前,参数在字符串资源中具有基本支持:
<resources><string name="str_template">Hello, %1$s! You have %2$d new messages.</string>
</resources>
使用带有可组合代码中的参数的字符串模板时,和 没有区别,例如:%...s%...d
Text(stringResource(Res.string.str_template, "User_name", 100))
字符串数组
您可以将相关字符串分组到一个数组中,并自动将它们作为对象访问:List<String>
<resources><string name="app_name">My awesome app</string><string name="title">Some title</string><string-array name="str_arr"><item>item \u2605</item><item>item \u2318</item><item>item \u00BD</item></string-array>
</resources>
要获取相应的List,请使用以下代码:
From 可组合代码
@Composable
fun stringArrayResource(resource: StringArrayResource): List<String> {...}
从不可组合代码
suspend fun getStringArray(resource: StringArrayResource): List<String>
例如:
coroutineScope.launch {val appName = getStringArray(Res.array.str_arr)
}
复数
当您的 UI 显示某物的数量时,您可能希望支持同一事物的不同数量(一本书、多本书等)的语法一致性,而无需创建以编程方式无关的字符串。
Compose Multiplatform 中的概念和基本实现与 Android 上的数量字符串相同。有关在项目中使用复数的最佳实践和细微差别的更多信息,请参阅 Android 文档。
-
支持的变体包括 、 、 、 、 和 。请注意,并非所有语言都会考虑所有变体:例如,对于英语,它会被忽略,因为它与除 1 之外的任何其他复数相同。依靠语言专家来了解该语言实际上坚持的区别。
zeroonetwofewmanyotherzero -
通常可以通过使用数量中立的公式(如 “Books: 1”)来避免数量字符串。如果这不会恶化用户体验,
要定义复数形式,请将元素添加到目录中的任何文件。集合是使用 name 属性(而不是 XML 文件的名称)引用的简单资源。因此,您可以在一个元素下的一个 XML 文件中将资源与其他简单资源组合在一起:<plurals>.xml composeResources/value splural splurals<resources>
<resources><string name="app_name">My awesome app</string><string name="title">Some title</string><plurals name="new_message"><item quantity="one">%1$d new message</item><item quantity="other">%1$d new messages</item></plurals>
</resources>
要将复数形式作为 a 访问,请使用以下代码:String
From 可组合代码
@Composable
fun pluralStringResource(resource: PluralStringResource, quantity: Int): String {...}@Composable
fun pluralStringResource(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String {...}
从不可组合代码
suspend fun getPluralString(resource: PluralStringResource, quantity: Int): Stringsuspend fun getPluralString(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String
例如:
coroutineScope.launch {val appName = getPluralString(Res.plurals.new_message, 1, 1)
}
字体
自定义字体存储在目录中 or files.composeResources/font*.ttf*.otf
要将字体加载为类型,请使用以下函数:Font Font()
@Composable
fun Font(resource: FontResource,weight: FontWeight = FontWeight.Normal,style: FontStyle = FontStyle.Normal
): Font
例如:
val fontAwesome = FontFamily(Font(Res.font.font_awesome))
Raw 文件
要将任何原始文件加载为字节数组,请使用以下函数:Res.readBytes(path)
suspend fun readBytes(path: String): ByteArray
您可以将原始文件放在目录中,并在其中创建任何层次结构。composeResources/files
例如,要访问原始文件,请使用以下代码:
From 可组合代码
var bytes by remember {mutableStateOf(ByteArray(0))
}
LaunchedEffect(Unit) {bytes = Res.readBytes("files/myDir/someFile.bin")
}
Text(bytes.decodeToString())
从不可组合代码
coroutineScope.launch {val bytes = Res.readBytes("files/myDir/someFile.bin")
}
将字节数组转换为图像
如果您正在读取的文件是位图(JPEG、PNG、BMP、WEBP)或 XML 矢量图像,则可以使用以下函数将它们转换为适合可组合项的对象。ImageBitmap ImageVector Image()
访问 Raw 文件部分所示的原始文件,然后将结果传递给可组合项:
// bytes = Res.readBytes("files/example.png")
Image(bytes.decodeToImageBitmap(), null)// bytes = Res.readBytes("files/example.xml")
Image(bytes.decodeToImageVector(LocalDensity.current), null)
在除 Android 之外的所有平台上,您还可以将 SVG 文件转换为对象:Painter
// bytes = Res.readBytes("files/example.svg")
Image(bytes.decodeToSvgPainter(LocalDensity.current), null)
为资源和字符串 ID 生成的映射
为了便于访问,Compose Multiplatform 还使用字符串 ID 映射资源。您可以使用文件名作为键来访问它们:
al Res.allDrawableResources: Map<String, DrawableResource>
val Res.allStringResources: Map<String, StringResource>
val Res.allStringArrayResources: Map<String, StringArrayResource>
val Res.allPluralStringResources: Map<String, PluralStringResource>
val Res.allFontResources: Map<String, FontResource>
将映射的资源传递给可组合项的示例:
Image(painterResource(Res.allDrawableResources["compose_multiplatform"]!!), null)
将多平台资源组合为 Android 资产
从 Compose Multiplatform 1.7.3 开始,所有多平台资源都打包到 Android 资产中。这样,Android Studio 就可以在 Android 源代码集中为 Compose Multiplatform 可组合项生成预览。
Android Studio 预览仅适用于 Android 源代码集中的可组合项。它们还需要最新版本的 AGP 之一:8.5.2、8.6.0-rc01 或 8.7.0-alpha04。
使用多平台资源作为 Android 资产还可以从 Android 上的 WebView 和媒体播放器组件直接访问,因为资源可以通过简单的路径访问,例如 .Res.getUri("files/index.html")
Android 可组合项显示带有资源图片链接的资源 HTML 页面的示例:
// androidMain/kotlin/com/example/webview/App.kt
@OptIn(ExperimentalResourceApi::class)
@Composable
@Preview
fun App() {MaterialTheme {val uri = Res.getUri("files/webview/index.html")// Adding a WebView inside AndroidView with layout as full screen.AndroidView(factory = {WebView(it).apply {layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)}}, update = {it.loadUrl(uri)})}
}
该示例适用于以下简单的 HTML 文件:
<html>
<header><title>Cat Resource</title>
</header>
<body><img src="cat.jpg">
</body>
</html>
此示例中的两个资源文件都位于源集中:commonMain

与其他库和资源的交互
从外部库访问多平台资源
如果要使用项目中包含的其他库处理多平台资源,则可以将特定于平台的文件路径传递给这些其他 API。要获取特定于平台的路径,请使用资源的工程路径调用函数:Res.getUri()
val uri = Res.getUri("files/my_video.mp4")
现在,变量包含文件的绝对路径,任何外部库都可以使用该路径以适合它的方式访问文件。uri
对于特定于 Android 的用途,多平台资源也打包为 Android 资产。
远程文件
在资源库的上下文中,只有属于应用程序的文件才被视为资源。
您可以使用专用库使用 Internet 的 URL 从远程文件加载远程文件:
-
编写 ImageLoader
-
Kamel
-
Ktor 客户端
使用 Java 资源
虽然您可以将 Java 资源与 Compose Multiplatform 结合使用,但它们无法从框架提供的扩展功能中受益:生成的访问器、多模块支持、本地化等。考虑完全过渡到多平台资源库以释放这种潜力。
在 Compose Multiplatform 1.7.3 中,软件包中提供的资源 API 已弃用。如果您仍需要使用 Java 资源,请将以下实现复制到您的项目中,以确保您的代码在升级到 Compose Multiplatform 1.7.0 或更高版本后仍能正常工作:compose.ui
@Composable
internal fun painterResource(resourcePath: String
): Painter = when (resourcePath.substringAfterLast(".")) {"svg" -> rememberSvgResource(resourcePath)"xml" -> rememberVectorXmlResource(resourcePath)else -> rememberBitmapResource(resourcePath)
}@Composable
internal fun rememberBitmapResource(path: String): Painter {return remember(path) { BitmapPainter(readResourceBytes(path).decodeToImageBitmap()) }
}@Composable
internal fun rememberVectorXmlResource(path: String): Painter {val density = LocalDensity.currentval imageVector = remember(density, path) { readResourceBytes(path).decodeToImageVector(density) }return rememberVectorPainter(imageVector)
}@Composable
internal fun rememberSvgResource(path: String): Painter {val density = LocalDensity.currentreturn remember(density, path) { readResourceBytes(path).decodeToSvgPainter(density) }
}private object ResourceLoader
private fun readResourceBytes(resourcePath: String) =ResourceLoader.javaClass.classLoader.getResourceAsStream(resourcePath).readAllBytes()
下一步是什么?
查看官方演示项目,该项目展示了如何在面向 iOS、Android 和桌面的 Compose Multiplatform 项目中处理资源。
相关文章:
【Compose multiplatform教程20】在应用程序中使用多平台资源
为项目设置资源后,生成项目以生成提供资源访问权限的特殊类。要重新生成类和所有资源访问器,请再次生成项目或在 IDE 中重新导入项目。ResRes 之后,您可以使用生成的类从您的代码或外部库访问配置的多平台资源。 自定义访问器类生成 您可以使…...
深入浅出:从入门到精通大模型Prompt、SFT、RAG、Infer、Deploy、Agent
阅读原文 渐入佳境 我们都知道,通过编写一个提示词(prompt),我们可以引导大模型生成回答,从而开启愉快的人工智能对话,比如让模型介绍一下卡皮巴拉。上边简图描述了这个过程,我们拆成两部分 pr…...
紫光同创-盘古200pro+开发板
本原创文章由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处(www.meyesemi.com) 一、开发系统介绍 开发系统概述 MES2L676-200HP 开发板采用紫光同创 logos2 系列 FPGA,型号:…...
iOS 中的 nil、Nil、NULL、NSNull 僵尸对象和野指针
iOS 中的 nil、Nil、NULL、NSNull 僵尸对象和野指针-CSDN博客 类型含义使用场景示例nil表示一个指向 Objective - C 对象的空指针。在 Objective - C 和 Swift(与 Objective - C 交互时)中用于表示对象不存在。当一个对象变量没有指向任何有效的对象实例…...
【优选算法】有效三角形的个数(双指针算法)
优质专栏:算法_云边有个稻草人的博客-CSDN博客 目录 【611. 有效三角形的个数 - 力扣(LeetCode)】 解法一: 解法二: 【611. 有效三角形的个数 - 力扣(LeetCode)】 解法一: 三层for…...
中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern)
中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern) 都是常见的设计模式,它们解决不同类型的问题。我们将通过 Swift 示例来说明它们的使用场景࿰…...
客户案例:基于慧集通打通聚水潭电商ERP与用友U8系统集成之路
一、引言 本原型客户是 生物科技公司,其公司系列抗菌抗病毒产品广泛应用于医疗用品、纺织服饰、家纺用品、母婴护理、女性用品、个人防护等多个领域。在知识产权方面,公司在专业领域已获得商标和专利近百项,创新能力得到了国家及行业内普遍认…...
阿里云clb是什么
传统型负载均衡服务 阿里云CLB(Classic Load Balancer)是阿里云提供的一种传统型负载均衡服务,主要用于将访问流量根据转发策略分发到后端多台云服务器。 CLB的定义和功能 CLB是一种流量分发控制服务,通过设置虚拟服务地…...
【Cursor编辑器】自用经验和实操(迭代更新)
1.启动composer crtl I 2.生成直接一直问加载 3. 实操 生成个知识图谱,使用csv文件里面的数据创关系和节点。...
【学习笔记】ChatGPT原理与应用开发——基础科普
HuggingLLM(ChatGPT原理与应用开发) 原文链接:HuggingLLM(ChatGPT原理与应用开发)-课程详情 | Datawhale 此处仅为学习记录和总结 1:基础科普 1.1:自然语言背景 图灵测试 如果一个人&#x…...
基于Web的实验中心工作管理网站的设计与实现
写作任务 一、课题背景 实验中心承担了全校计算机公共基础课程和学院专业课程,需要对实验中心工作进行有效的管理。 二、课题任务 本课题设计和实现实验中心工作管理系统。 系统的主要内容包括: (1)人员管理; &am…...
docker 安装minio
docker pull minio/minio #启动 mkdir -p /root/minio/config mkdir -p /root/minio/datadocker run -d \--name minio \-p 9002:9000 \-p 9001:9001 \--restartalways \-v /root/minio/data:/data \-v /root/minio/config:/root/.minio \-e "MINIO_ACCESS_KEYminioadmin…...
ubuntu下ipmi的使用(4028)
参考ubuntu系统下配置IPMI_ubuntu ipmi-CSDN博客 参考:ipmitool ubuntu 安装_ipmi centos ubuntu使用总结-CSDN博客 1.安装 sudo apt-get -y install ipmitool 2.加载 modprobe ipmi_msghandlermodprobe ipmi_devintfmodprobe ipmi_si 3.使用,查看不到的话&am…...
周记-唐纳德的《计算机程序设计艺术》
用代码生成代码 开发一个协议,字段有些多,每个字段是QT的属性,需要写Q_PROPERTY,一个一个编辑的话比较繁琐,耗费时间。后来就用代码生成了头文件和源文件,get和set还有signal函数,内容基本都是…...
极品飞车6的快捷键与车辆等级
极品飞车,英文全称为Need for Speed,是EA公司于1994年开始研发的赛车类竞技游戏。从1996年的《极品飞车-特别版》、2002年的《极品飞车:闪电追踪2》、2005年的《极品飞车:地下狂飙2》、到2024年《极品飞车:集结》,是70后、80年、90年等几代人…...
计算机毕业设计Python+知识图谱大模型AI医疗问答系统 健康膳食推荐系统 食谱推荐系统 医疗大数据 机器学习 深度学习 人工智能 爬虫 大数据毕业设计
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
纯真社区版IP库CZDB数据格式使用教程
1. 概述 纯真社区版IP库是一种免费且公开的IP地理位置数据库,主要面向非商业用途。其最新推出的CZDB格式是一种全新的数据文件格式,自2024年10月起将成为官方维护和更新的唯一版本。该格式支持同时存储IPv4和IPv6地址信息,具备以下优点&…...
Linux(Centos 7.6)软件包安装
Linux软件安装,常见的有三种方式,rpm方式、yum方式、源码编译安装方式。其中rpm方式可能存在依赖方式,可能会比较麻烦;源码编译安装同样可能会缺少一些编译需要的软件需要安装,也会比较麻烦;相对比较好的方…...
[WASAPI]音频API:从Qt MultipleMedia走到WASAPI,相似与不同
[WASAPI] 从Qt MultipleMedia 来看WASAPI 最近在学习有关Windows上的音频驱动相关的知识,在正式开始说WASAPI之前,我想先说一说Qt的Multiple Media,为什么呢?因为Qt的MultipleMedia实际上是WASAPI的一层封装,它在是线…...
【畅购商城】微信支付之支付模块
目录 支付页面 接口 后端实现 前端实现 支付页面 步骤一:创建 flow3.vue组件 步骤二:引入第三方资源(js、css) <script> import TopNav from ../components/TopNav import Footer from …...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目
应用场景: 1、常规某个机器被钓鱼后门攻击后,我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后,我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...
