当前位置: 首页 > news >正文

Compose 适配 - 自定义主题

参考文章1

参考文章2

一、概念

创建项目之后,就会生成一个 项目名称+Theme 的 @Compose 函数,我们可以通过更改其中的颜色来完成对主题的修改。硬编码在配置的地方把值写死会无法支持主题切换,应该从主题中引用对应值,由于每个值都是实例还能通过 copy() 修改。

二、步骤

2.1 定义不同版本的颜色名称和值

方式一:在 Color.kt 中定义颜色的不同版本名称和值。

object AppColors { //正文 val textPrimary_Light = Color(0xCC000000) val textPrimary_Dark = Color(0xFF626567) //红色 val red = Color(0xFFFF0000) val red50 = Color(0x80FF0000) //透明 val transparent = Color(0x00FFFFFF) }

方式二:在 res/values/colors.xml 中定义颜色的不同版本名称和值。

<resources> //正文 <color name="textPrimary_Light">#CC000000</color> <color name="textPrimary_Dark">#FF626567</color> //红色 <color name="red">#FFFF0000</color> <color name="red50">#80FF0000</color> //透明 <color name="transparent">#00FFFFFF</color> </resources>

2.2 定义颜色集基类

  1. 在 Theme.kt 中创建颜色集类。
  2. 构造中塞入颜色名称供创建实例的时候指定具体颜色。
  3. 定义对应的属性并通过 MutableState 包裹提供状态,以便发生改变时所有引用该颜色的组合项会重组。
  4. 提供 copy() 支持调用处修改某个颜色。(可选)
class ThemeColors( //定义需要的颜色名称 textPrimary: Color, background: Color, ) { //颜色是有状态的,发生改变时所有引用这个颜色的组合项都会重组 var textPrimary by mutableStateOf(textPrimary) private set var background by mutableStateOf(background) private set //提供copy支持调用处修改某个颜色 // fun copy( // textPrimary: Color = this.textPrimary, // background: Color = this.background, // ): ThemeColors = ThemeColors( // textPrimary = textPrimary, // background = background, // ) }

2.3 创建不同的颜色集实例(不同的主题色)

在 Theme.kt 中,创建不同的颜色集实例(即不同的主题),构造中指定具体的颜色值。暂不推荐从xml中读取,通过主题调用的颜色显示错误,未找到原因

//亮色主题(举例从 Color.kt 中读取) private val LightColors = ThemeColors( textPrimary = AppColors.TextPrimary_Light, background = AppColors.transparent, ) //暗色主题(举例从 colors.xml 中读取) private val DarkColors = ThemeColors( textPrimary = Color(R.color.textPrimary_Dark), background = Color(R.color.transparent), )

2.4 定义全局调用入口

在 Theme.kt 中,声明一个由 CompositionLocal 包装的变量用来获取颜色集实例,声明一个单例用作全局调用入口,还包含了对类型的判断。

//声明一个CompositionLocal变量供调用处获取自定义的颜色集实例 //颜色集对象中的颜色值是确定的不会更改的,因此使用staticCompositionLocalOf 的提高性能 //设为private收纳进AppTheme中从统一入口获取,比起通过 LocalXXX 获取更符合直觉 private val LocalAppColors = staticCompositionLocalOf { LightColors } //声明一个单例,用作全局入口 object AppTheme { //用于获取自定义的颜色集 val colors: ThemeColors @Composable get() = LocalAppColors.current //提供枚举类用于传参判断类型 enum class ColorsType { LIGHT, DARK } }

2.5 提供切换功能

@Composable fun AppTheme( colorsType: AppTheme.ColorsType = AppTheme.ColorsType.LIGHT, //指定颜色集 darkTheme: Boolean = isSystemInDarkTheme(), //自动识别是否开启暗黑模式 content: @Composable () -> Unit //需要包裹的内容 ) { //获取指定的颜色方案并添加动画(避免切换的时候一闪) val themeColors = if (darkTheme) addAnimationToAPPColors(DarkColors) else{ when (colorsType) { AppTheme.ColorsType.LIGHT -> addAnimationToThemeColors(LightColors) AppTheme.ColorsType.DARK -> addAnimationToThemeColors(DarkColors) } } //提供出去 CompositionLocalProvider(LocalAppColors provides themeColors){ //同时使用MaterialTheme的话就在这里包裹一下 content() } }

2.6 添加切换动画(避免直接一闪)

/** * 为自定义颜色集添加过度动画(避免直接一闪) */ @Composable private fun addAnimationToThemeColors(themeColors: ThemeColors) = ThemeColors( textPrimary = animateColorAsState(themeColors = targetColor.textPrimary, TweenSpec(600), label = "textPrimary").value, background = animateColorAsState(themeColors = targetColor.background, TweenSpec(600), label = "background ").value, )

2.7 组合项中调用颜色

Text(text = "", color = AppTheme.colors.textPrimary)
http://www.jsqmd.com/news/1235590/

相关文章:

  • smsBomb安全测试实战:10个步骤教你进行短信轰炸安全测试
  • Mysql时间分组
  • TILER技术解析:二维平铺内存如何突破嵌入式图像处理的内存墙
  • 从EAGLE schematic到实际运行:Spark Thermostat硬件开发全流程
  • 【小程序毕业设计】基于微信小程序的宿舍日常与防疫管理平台 高校宿舍出入报备与防疫管理小程序(源码+文档+远程调试,全bao定制等)
  • redis持久化RDB与AOF
  • 亳州专升本机构避坑指南!认准库课“连续4年通过率第一”认证,2026稳扎稳打上本科 - 我叫小周
  • OpenCode 2.0 发布:重构 API、迁移运行环境,解决内存与排队难题!
  • 终极Node.js命令行解析工具command-line-args:10分钟快速入门指南
  • 规避90新手误区闲置沃尔玛电子卡安全变现完整解析 - 优企甄选
  • 2026年贵阳防水补漏行业实测盘点 本地业主房屋修缮靠谱团队甄选指南 - 吉林同城获客
  • Slide开源Reddit浏览器:终极无广告Android客户端完全指南
  • 2026年,专业果蔬清洗机该如何选择?哪家才是最佳之选?
  • 2026常州发越南物流专线哪个好?2026 福要供应链陆运专线时效稳定收费透明 - 资讯速览
  • EServer深度解析:现代化本地开发环境管理平台架构剖析与高级实践指南
  • Backbone.offline错误处理指南:应对网络中断与存储限制的终极方案
  • 【紧急预警】你的AI API平均延迟已超867ms——这份实测TOP10模型响应排行榜,今天不看明天上线就卡顿!
  • AI提示词工程师副业指南,手把手教你接单、定价、交付,3类高单价客户精准锁定
  • 一键获取国家中小学智慧教育平台电子课本:免费PDF下载终极指南
  • 深入解析C2000 eQEP模块:从正交编码器原理到精准运动控制实战
  • windows笔记(一)
  • Tack自动化运维:使用Makefile和脚本简化Kubernetes集群管理
  • 深度解析:REFramework如何高效修复《街霸6》在线对战软锁问题
  • 北京回收市场惊现“抢金潮”,但专家泼冷水:报价高出大盘15元以上的统统有诈 - 日常比对手册
  • 2026升级:九江德安县全城家电维修推荐惠民联统一报修 - 余生黄金回收
  • Claude Code Skill 从入门到精通:自动化编码任务实战指南
  • 【小程序毕业设计】基于 SpringBoot 的物资采购供货与库存管理平台 商户供货订单流转管理小程序设计(源码+文档+远程调试,全bao定制等)
  • 为什么选择command-line-args?深度解析5大核心优势与使用场景
  • 从工具使用者到AI协作者,深度转型路径全拆解,含6套可落地的个人AI工作流模板
  • 面向对象的思考