繁体   English   中英

Android Jetpack Compose(Composable) 平滑更改主题颜色

[英]Android Jetpack Compose(Composable) Change Theme Color Smoothly

由于我不想使用基础 Colors class,因此我想使用我自己的 colors 既不用于按钮也不用于文本元素。 所以我创建了自己的 Colors class 以及相应的浅色和深色调色板类。 然后在我的可组合中,我想更改主题颜色,但使用 animation,这就是我使用animateColorAsState的原因,但代码看起来很丑陋。 有没有办法为所有 colors 设置动画,而无需分别为每种颜色定义 animateColorAsState?

这是结果
在此处输入图像描述

自定义调色板的代码

@Stable
class Colors(
    background: Color,
    line90DegColor: Color,
    hoursArrowColor: Color,
    secondsArrowColor: Color,
    baseColor: Color,
    lighter: Color,
    darker: Color,
    baseColorLessTransparent: Color,
    baseColorSemiTransparent: Color,
    baseColorTransparent: Color
) {
    var background by mutableStateOf(background, structuralEqualityPolicy())
        internal set

    var line90DegColor by mutableStateOf(line90DegColor, structuralEqualityPolicy())
        internal set

    // same for the rest of the colors

}

val LightColorPalette = Colors(
    background = Color(0xFFECECF3),
    line90DegColor = Color(0xFF9B9BB0),
    // same for the rest of the colors
)

val DarkColorPalette = Colors(
    background = Color(0xFF25252D),
    line90DegColor = Color(0xFF9B9BB0),
    // same for the rest of the colors
)

可组合代码,其中 colors 是通过animateColorAsState更改的

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        setContent {

            var isLightTheme by remember {
                mutableStateOf(true)
            }
            val colors = if (isLightTheme) {
                LightColorPalette
            } else {
                DarkColorPalette
            }

            // create color state for each of the theme color
            val animationSpec: AnimationSpec<Color> = tween(durationMillis = 1500)
            val background by animateColorAsState(colors.background, animationSpec)
            val line90DegColor by animateColorAsState(colors.line90DegColor, animationSpec)
            val hoursArrowColor by animateColorAsState(colors.hoursArrowColor, animationSpec)
            val secondsArrowColor by animateColorAsState(colors.secondsArrowColor, animationSpec)
            val baseColor by animateColorAsState(colors.baseColor, animationSpec)
            val lighter by animateColorAsState(colors.lighter, animationSpec)
            val darker by animateColorAsState(colors.darker, animationSpec)
            val baseColorLessTransparent by animateColorAsState(colors.baseColorLessTransparent, animationSpec)
            val baseColorSemiTransparent by animateColorAsState(colors.baseColorSemiTransparent, animationSpec)
            val baseColorTransparent by animateColorAsState(colors.baseColorTransparent, animationSpec)

            // create new Colors object that matches the current theme
            val animatedColors = Colors(
                background,
                line90DegColor,
                hoursArrowColor,
                secondsArrowColor,
                baseColor,
                lighter,
                darker,
                baseColorLessTransparent,
                baseColorSemiTransparent,
                baseColorTransparent
            )

            ClockWidget(animatedColors, hours, minutes, seconds) {
                isLightTheme = !isLightTheme
            }
        } 
    }
}

我想你可以尝试将你的代码包装到 AnimationContent 与targetState = your theme多么简单的方法。 或者你可以这样写:

@Stable
data class Colors(
    val background: Color,
    val line90DegColor: Color,
    val hoursArrowColor: Color,
    val secondsArrowColor: Color,
    val baseColor: Color,
    val lighter: Color,
    val darker: Color,
    val baseColorLessTransparent: Color,
    val baseColorSemiTransparent: Color,
    val baseColorTransparent: Color
) {
    private val animationSpec: AnimationSpec<Color> = tween(durationMillis = 1500)

    @Composable
    private fun animateColor(
        targetValue: Color,
        finishedListener: ((Color) -> Unit)? = null
    ) = animateColorAsState(targetValue = targetValue, animationSpec = animationSpec).value
    
    @Composable
    fun switch() = copy(
        background = animateColor(background),
        secondsArrowColor = animateColor(secondsArrowColor),
        lighter = animateColor(lighter),
        darker = animateColor(darker),
        //etc
    )

并将您的变量 animatedColors 更改为

val animatedColors = (if (isLightTheme) LightColorPalette else DarkColorPalette).switch()

我建议您阅读有关CompositionLocal 的内容

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM