Android 12 Developer Preview is here! Try it out, and give us your feedback!


class InfiniteTransition
   ↳ androidx.compose.animation.core.InfiniteTransition

InfiniteTransition is responsible for running child animations. Child animations can be added using InfiniteTransition.animateColor, InfiniteTransition.animateFloat, or InfiniteTransition.animateValue. Child animations will start running as soon as they enter the composition, and will not stop until they are removed from the composition.

import androidx.compose.animation.animateColor
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.material.Icon

fun InfinitelyPulsingHeart() {
    // Creates an [InfiniteTransition] instance for managing child animations.
    val infiniteTransition = rememberInfiniteTransition()

    // Creates a child animation of float type as a part of the [InfiniteTransition].
    val scale by infiniteTransition.animateFloat(
        initialValue = 3f,
        targetValue = 6f,
        animationSpec = infiniteRepeatable(
            // Infinitely repeating a 1000ms tween animation using default easing curve.
            animation = tween(1000),
            // After each iteration of the animation (i.e. every 1000ms), the animation will
            // start again from the [initialValue] defined above.
            // This is the default [RepeatMode]. See [RepeatMode.Reverse] below for an
            // alternative.
            repeatMode = RepeatMode.Restart

    // Creates a Color animation as a part of the [InfiniteTransition].
    val color by infiniteTransition.animateColor(
        initialValue = Color.Red,
        targetValue = Color(0xff800000), // Dark Red
        animationSpec = infiniteRepeatable(
            // Linearly interpolate between initialValue and targetValue every 1000ms.
            animation = tween(1000, easing = LinearEasing),
            // Once [TargetValue] is reached, starts the next iteration in reverse (i.e. from
            // TargetValue to InitialValue). Then again from InitialValue to TargetValue. This
            // [RepeatMode] ensures that the animation value is *always continuous*.
            repeatMode = RepeatMode.Reverse

    Box(Modifier.fillMaxSize()) {
            contentDescription = null,
            modifier = Modifier.align(Alignment.Center)
                    scaleX = scale,
                    scaleY = scale
            tint = color


Extension functions
From androidx.compose.animation
InfiniteTransition.animateColor(initialValue: Color, targetValue: Color, animationSpec: InfiniteRepeatableSpec<Color>)

Creates a Color animation that runs infinitely as a part of the given InfiniteTransition.

From androidx.compose.animation.core
InfiniteTransition.animateFloat(initialValue: Float, targetValue: Float, animationSpec: InfiniteRepeatableSpec<Float>)

Creates an animation of Float type that runs infinitely as a part of the given InfiniteTransition.

InfiniteTransition.animateValue(initialValue: T, targetValue: T, typeConverter: TwoWayConverter<T, V>, animationSpec: InfiniteRepeatableSpec<T>)

Creates an animation of type T that runs infinitely as a part of the given InfiniteTransition.