参考文章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 nametextPrimary_Light#CC000000/color color nametextPrimary_Dark#FF626567/color //红色 color namered#FFFF0000/color color namered50#80FF0000/color //透明 color nametransparent#00FFFFFF/color /resources2.2 定义颜色集基类在 Theme.kt 中创建颜色集类。构造中塞入颜色名称供创建实例的时候指定具体颜色。定义对应的属性并通过 MutableState 包裹提供状态以便发生改变时所有引用该颜色的组合项会重组。提供 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)