I need to create following animation in Jetpack: ...
# compose
m
I need to create following animation in Jetpack: Text is normally gray, when some event occurs (lets say message arrived) the text become green and fade out slowly back to gray. I did it with ObectAnimator and its .start() method in "classic old" XML layouts, but canot find any usable example for Jetpack. All examples are switching between true/false variable and based on it are animating color transition. It is not usable for my case, as I need trigger one time transition from green to gray.
m
do you mean that when message arrived then text immediately turns green without any delay right? but form green to gray you want slow animation
you can use animate*AsState api and also specify the duration as per your condidtion
m
Yes, it is exactly what I need. Once message arrive, text become green immediatelly and then slowly change back to gray. I tried to play with animate*AsState but did not find any usable example. All examples implements observable Boolean, change (negate) its value with button and animate colors based on this value. I need to fire one time animation not change color on false/true basis.
I did it in XML layuots in following manner:
Copy code
val colorAnim = ObjectAnimator.ofInt(
                binding!!.tvLiveDataSource, "textColor",
                Color.argb(255, 173, 255, 0), Color.argb(255, 33, 49, 0)
            )
            colorAnim.duration = 5000
            colorAnim.setEvaluator(ArgbEvaluator())
            colorAnim.start()
I would appreciate if someone can provide me a piece of code with example
m
i'll send the snippet in sometime.
z
Use Animatable and launch a call to animateTo on click
m
Thanks Zach, may I ask you for some quick example for this technique ?
o
Yeap,
Animatable
is a more correct API for this case.
Copy code
Column(
    verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically),
    horizontalAlignment = Alignment.CenterHorizontally,
    modifier = Modifier.fillMaxSize()
) {
    // You should create a variable for coroutine scope, because ".snapTo"
    // and ".animateTo" are suspend methods
    val scope = rememberCoroutineScope()

    // Then you need to remember a new "Animatable" instance with some initial value
    val color = remember { Animatable(Color(0xFF213100)) }

    // To get the current value of the "Animatable" you should use "value" property
    Text(
        text = "Some Colorful Text",
        color = color.value,
    )

    Button(
        onClick = {
            // On button click, or on some external event you should launch a new
            // coroutine where you snap a color immediately to the Green color and
            // then animate the color to the Gray during 5000ms duration
            scope.launch {
                color.snapTo(Color(0xFFAEFF00))
                color.animateTo(
                    targetValue = Color(0xFF213100),
                    animationSpec = tween(
                        durationMillis = 5_000
                    )
                )
            }
        }
    ) {
        Text(text = "New Message")
    }
}
Column(
    verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically),
    horizontalAlignment = Alignment.CenterHorizontally,
    modifier = Modifier.fillMaxSize()
) {
    // You should create a variable for coroutine scope, because ".snapTo"
    // and ".animateTo" are suspend methods
    val scope = rememberCoroutineScope()
    // Then you need to remember a new "Animatable" instance with some initial value
    val color = remember { Animatable(Color(0xFF213100)) }
    // To get the current value of the "Animatable" you should use "value" property
    Text(
        text = "Some Colorful Text",
        color = color.value,
    )
    Button(
        onClick = {
            // On button click, or on some external event you should launch a new
            // coroutine where you snap a color immediately to the Green color and
            // then animate the color to the Gray during 5000ms duration
            scope.launch {
                color.snapTo(Color(0xFFAEFF00))
                color.animateTo(
                    targetValue = Color(0xFF213100),
                    animationSpec = tween(
                        durationMillis = 5_000
                    )
                )
            }
        }
    ) {
        Text(text = "New Message")
    }
}
m
Many many thanks Oleksandr, it is exactly what I need. Very appreciate your help !
👍 1