Build apps faster with our new App builder! Check it out →

AnimatedText

Android

Component in Wear Material 3 Compose

A composable that displays an animated text.

AnimatedText can be used to animate a text along font variation axes and size. It requires an [AnimatedTextFontRegistry] to improve performance.

[AnimatedTextFontRegistry] can be generated using [rememberAnimatedTextFontRegistry] method, which requires start and end font variation axes, and start and end font sizes for the animation.

Start of the animation is when the animatable is at 0f and end of the animation is when the animatable is at 1f. Current animation progress is provided by the [progressFraction] function. This should be between 0f and 1f, but might go beyond in some cases such as overshooting spring animations.

Example of a one-shot animation with AnimatedText

Last updated:

Installation

dependencies {
   implementation("androidx.wear.compose:compose-material3:1.0.0-alpha27")
}

Overloads

@Composable
@RequiresApi(31)
fun AnimatedText(
    text: String,
    fontRegistry: AnimatedTextFontRegistry,
    progressFraction: () -> Float,
    modifier: Modifier = Modifier,
    contentAlignment: Alignment = Alignment.Center,
)

Parameters

namedescription
textThe text to be displayed.
fontRegistryThe font registry to be used to animate the text.
progressFractionA provider for the current state of the animation. Provided value should be between 0f and 1f, but might go beyond in some cases such as overshooting spring animations.
modifierModifier to be applied to the composable.
contentAlignmentAlignment within the bounds of the Canvas.

Code Examples

AnimatedTextSample

@Composable
fun AnimatedTextSample() {
    val animatable = remember { Animatable(0f) }
    val animatedTextFontRegistry =
        rememberAnimatedTextFontRegistry(
            // Variation axes at the start of the animation, width 10, weight 200
            startFontVariationSettings =
                FontVariation.Settings(
                    FontVariation.width(10f),
                    FontVariation.weight(200),
                ),
            // Variation axes at the end of the animation, width 100, weight 500
            endFontVariationSettings =
                FontVariation.Settings(
                    FontVariation.width(100f),
                    FontVariation.weight(500),
                ),
            startFontSize = 30.sp,
            endFontSize = 40.sp,
        )
    AnimatedText(
        text = "Hello!",
        fontRegistry = animatedTextFontRegistry,
        // Content alignment anchors the animation at the vertical center, expanding horizontally
        contentAlignment = Alignment.CenterStart,
        progressFraction = { animatable.value },
    )
    LaunchedEffect(Unit) {
        // Animate from 0 to 1 and then back to 0.
        animatable.animateTo(1f)
        animatable.animateTo(0f)
    }
}

AnimatedTextSampleButtonResponse

@Composable
fun AnimatedTextSampleButtonResponse() {
    val scope = rememberCoroutineScope()
    val animatedTextFontRegistry =
        rememberAnimatedTextFontRegistry(
            // Variation axes at the start of the animation, width 10, weight 200
            startFontVariationSettings =
                FontVariation.Settings(
                    FontVariation.width(10f),
                    FontVariation.weight(200),
                ),
            // Variation axes at the end of the animation, width 100, weight 500
            endFontVariationSettings =
                FontVariation.Settings(
                    FontVariation.width(100f),
                    FontVariation.weight(500),
                ),
            startFontSize = 30.sp,
            endFontSize = 40.sp,
        )
    val firstNumber = remember { mutableIntStateOf(0) }
    val firstAnimatable = remember { Animatable(0f) }
    val secondNumber = remember { mutableIntStateOf(0) }
    val secondAnimatable = remember { Animatable(0f) }
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        AnimatedText(
            text = "${firstNumber.value}",
            fontRegistry = animatedTextFontRegistry,
            progressFraction = { firstAnimatable.value },
        )
        Button(
            onClick = {
                firstNumber.value += 1
                scope.launch {
                    firstAnimatable.animateTo(1f)
                    firstAnimatable.animateTo(0f)
                }
            },
            label = { Text("+") }
        )
        AnimatedText(
            text = "${secondNumber.value}",
            fontRegistry = animatedTextFontRegistry,
            progressFraction = { secondAnimatable.value },
        )
        Button(
            onClick = {
                secondNumber.value += 1
                scope.launch {
                    secondAnimatable.animateTo(1f)
                    secondAnimatable.animateTo(0f)
                }
            },
            label = { Text("+") }
        )
    }
}

AnimatedTextSampleSharedFontRegistry

@Composable
fun AnimatedTextSampleSharedFontRegistry() {
    val animatedTextFontRegistry =
        rememberAnimatedTextFontRegistry(
            // Variation axes at the start of the animation, width 10, weight 200
            startFontVariationSettings =
                FontVariation.Settings(
                    FontVariation.width(10f),
                    FontVariation.weight(200),
                ),
            // Variation axes at the end of the animation, width 100, weight 500
            endFontVariationSettings =
                FontVariation.Settings(
                    FontVariation.width(100f),
                    FontVariation.weight(500),
                ),
            startFontSize = 15.sp,
            endFontSize = 25.sp,
        )
    val firstAnimatable = remember { Animatable(0f) }
    val secondAnimatable = remember { Animatable(0f) }
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        AnimatedText(
            text = "Top Text",
            fontRegistry = animatedTextFontRegistry,
            progressFraction = { firstAnimatable.value },
        )
        AnimatedText(
            text = "Bottom Text",
            fontRegistry = animatedTextFontRegistry,
            progressFraction = { secondAnimatable.value },
        )
    }
    LaunchedEffect(Unit) {
        firstAnimatable.animateTo(1f)
        firstAnimatable.animateTo(0f)
        secondAnimatable.animateTo(1f)
        secondAnimatable.animateTo(0f)
    }
}
by @alexstyl