'Android Jetpack Compose(Composable) Change Theme Color Smoothly

Since I don't want to use the base Colors class, instead I want to use my own colors that are not used in neither buttons or text elements. So I created my own Colors class with the corresponding light and dark palette classes. Then in my composable I want to change the theme color, but using animation, this is why I used animateColorAsState, but the code looks very ugly. Is there a way to animate all the colors, without defining animateColorAsState for each color separately?

Here is the result
enter image description here

Code for the custom color palettes

@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
)

Code for the composable, where the colors are changes via 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
            }
        } 
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source