Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android jetpack compose countdown animation [closed]

Is it possible to make an animation like gif with Jetpack Compose?

enter image description here

like image 764
Vahit Keskin Avatar asked Jun 24 '26 21:06

Vahit Keskin


2 Answers

One of the ways to do is using Animatables that animate scale and alpha after each other.

enter image description here

create a class that contains 2 Animatables

class AnimatedCountdownTimer(
    private val coroutineScope: CoroutineScope
) {

    private val animatableScale = Animatable(1f)
    private val animatableAlpha = Animatable(1f)

    val scale: Float
        get() = animatableScale.value

    val alpha: Float
        get() = animatableAlpha.value

    fun start(initialValue: Int, endValue: Int, onChange: (Int) -> Unit) {

        var value = initialValue

        coroutineScope.launch {
            while (value > endValue - 1) {
                onChange(value)
                animatableScale.snapTo(1f)
                animatableAlpha.snapTo(1f)
                animatableScale.animateTo(2f, animationSpec = tween(750))
                animatableAlpha.animateTo(0f, animationSpec = tween(250))
                value--

            }
        }
    }
}

And use it as

@Preview
@Composable
fun TimerTest() {


    var timer by remember {
        mutableStateOf(5)
    }

    val coroutineScope = rememberCoroutineScope()

    val animatedCountdownTimer = remember {
        AnimatedCountdownTimer(coroutineScope)
    }

    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            modifier = Modifier.graphicsLayer {
                scaleX = animatedCountdownTimer.scale
                scaleY = animatedCountdownTimer.scale
                alpha = animatedCountdownTimer.alpha
            },
            text = "$timer",
            fontSize = 120.sp,
            fontWeight = FontWeight.Bold,
            color = Color.Gray
        )
        Spacer(Modifier.height(20.dp))
        Button(
            modifier = Modifier.fillMaxWidth(),
            onClick = {
                animatedCountdownTimer.start(5, 0) {
                    timer = it
                }
            }
        ) {
            Text("Start")
        }
    }
}

If you don't want to scale to 1f after animation end just ad if block so it can stay at scale. Any param can be customized easily time durations or max scale.

If you wish to keep last number scaled you can use it like this

  coroutineScope.launch {
        while (value > endValue - 1) {
            onChange(value)
            animatableScale.snapTo(1f)
            animatableAlpha.snapTo(1f)
            animatableScale.animateTo(2f, animationSpec = tween(750))
            if (value > endValue) {
                animatableAlpha.animateTo(0f, animationSpec = tween(250))
            }
            value--
        }
    }
like image 137
Thracian Avatar answered Jun 26 '26 10:06

Thracian


Absolutely! You will need LaunchedEffect and mutableStateOf composables to manage the state of the timer and update.

enter image description here

@Composable
fun CountdownTimer() {
    val totalTime = 5 // Total time in seconds
    var restart by remember { mutableStateOf(0) }
    var timeLeft by remember {
        mutableStateOf(totalTime)
    }
    val anim = remember { Animatable(0f) }

    LaunchedEffect(restart) {
        while (timeLeft > 0) {
            delay(1000)
            timeLeft--
            anim.snapTo(0f)
            anim.animateTo(1f)
        }
    }

    Column (
        horizontalAlignment=Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ){
        Text(
            modifier = Modifier
                .alpha(anim.value)
                .scale(anim.value/2f+.5f)
            ,
            text = "${timeLeft}",
            fontSize = 64.sp,
            color = Color.DarkGray
        )

        Button(onClick = {
            timeLeft = totalTime
            restart++
        }) {
            Text(text = "Reset")
        }
    }
}
like image 24
ucMedia Avatar answered Jun 26 '26 09:06

ucMedia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!