AnimatedText

Functions summary

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

A composable that displays an animated text.

Functions

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

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

import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.clickable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontVariation
import androidx.compose.ui.unit.sp
import androidx.wear.compose.material3.AnimatedText
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.rememberAnimatedTextFontRegistry

val scope = rememberCoroutineScope()
val animatable = remember { Animatable(0f) }
val animate = {
    scope.launch {
        // Animate from 0 to 1 and then back to 0.
        animatable.animateTo(1f)
        animatable.animateTo(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 },
    modifier = Modifier.clickable(onClick = { animate() }),
)
LaunchedEffect(Unit) { animate() }

Example of an animation in response to a button press with AnimatedText

import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontVariation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.material3.AnimatedText
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.rememberAnimatedTextFontRegistry

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 = 30.sp,
    )
val number = remember { mutableIntStateOf(0) }
val textAnimatable = remember { Animatable(0f) }
Row(verticalAlignment = Alignment.CenterVertically) {
    Button(
        modifier = Modifier.padding(horizontal = 16.dp),
        onClick = {
            number.value -= 1
            scope.launch {
                textAnimatable.animateTo(1f)
                textAnimatable.animateTo(0f)
            }
        },
        label = {
            Text(modifier = Modifier.semantics { contentDescription = "Decrease" }, text = "-")
        },
    )
    AnimatedText(
        text = "${number.value}",
        fontRegistry = animatedTextFontRegistry,
        progressFraction = { textAnimatable.value },
    )
    Button(
        modifier = Modifier.padding(horizontal = 16.dp),
        onClick = {
            number.value += 1
            scope.launch {
                textAnimatable.animateTo(1f)
                textAnimatable.animateTo(0f)
            }
        },
        label = {
            Text(modifier = Modifier.semantics { contentDescription = "Increase" }, text = "+")
        },
    )
}

Example showing how AnimatedTextFontRegistry can be reused and shared between two AnimatedText composables

import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.text.font.FontVariation
import androidx.compose.ui.unit.sp
import androidx.wear.compose.material3.AnimatedText
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.rememberAnimatedTextFontRegistry

val animatedTextFontRegistry =
    rememberAnimatedTextFontRegistry(
        // Variation axes at the start of the animation, width 50, weight 300
        startFontVariationSettings =
            FontVariation.Settings(FontVariation.width(50f), FontVariation.weight(300)),
        // Variation axes at the end of the animation are the same as the start axes
        endFontVariationSettings =
            FontVariation.Settings(FontVariation.width(50f), FontVariation.weight(300)),
        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)
}
Parameters
text: String

The text to be displayed.

fontRegistry: AnimatedTextFontRegistry

The font registry to be used to animate the text.

progressFraction: () -> Float

A 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.

modifier: Modifier = Modifier

Modifier to be applied to the composable.

contentAlignment: Alignment = Alignment.Center

Alignment within the bounds of the Canvas.