Compose Component

TimeText

Layout to show the current time and a label at the top of the screen.

TimeTextWithStatus

@Sampled
@Composable
fun TimeTextWithStatus() {
    val leadingTextStyle = TimeTextDefaults.timeTextStyle(color = MaterialTheme.colors.primary)

    TimeText(
        startLinearContent = { Text(text = "ETA 12:48", style = leadingTextStyle) },
        startCurvedContent = {
            curvedText(text = "ETA 12:48", style = CurvedTextStyle(leadingTextStyle))
        },
    )
}

TimeTextWithFullDateAndTimeFormat

@Sampled
@Composable
fun TimeTextWithFullDateAndTimeFormat() {
    TimeText(
        timeSource =
            TimeTextDefaults.timeSource(
                DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy-MM-dd hh:mm")
            )
    )
}

TimeTextAnimation

@Sampled
@Composable
fun TimeTextAnimation() {
    var showState by remember { mutableStateOf(false) }
    val showTransition = updateTransition(showState)

    val time = 350
    val animatedColor by
        showTransition.animateColor(
            label = "animatedColor",
            transitionSpec = {
                tween(
                    time,
                    easing =
                        when {
                            false isTransitioningTo true ->
                                // Fade In
                                CubicBezierEasing(0.4f, 0.0f, 1.0f, 1.0f)
                            else ->
                                // Fade Out
                                CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)
                        },
                )
            },
        ) { state ->
            when (state) {
                true -> Color.White
                false -> Color.Transparent
            }
        }
    val animateSize by
        showTransition.animateFloat(
            label = "animatedSize",
            transitionSpec = { tween(time, easing = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f)) },
        ) { state ->
            when (state) {
                true -> 1f
                false -> 0f
            }
        }

    val text = "Long text to animate"

    val curvedSeparatorSweep = 10f
    val curvedTextSweep = 80f
    val curvedAnimatedSweep = animateSize * (curvedSeparatorSweep + curvedTextSweep)
    val curvedSeparatorGap = curvedAnimatedSweep.coerceAtMost(curvedSeparatorSweep) / 2f

    val linearSeparatorSize = 10.dp
    val linearTextSize = 70.dp
    val linearAnimatedSize = animateSize * (linearSeparatorSize + linearTextSize)
    val linearSeparatorGap = linearAnimatedSize.coerceAtMost(linearSeparatorSize) / 2f

    val textStyle =
        TimeTextDefaults.timeTextStyle().copy(fontWeight = FontWeight.Normal, color = animatedColor)
    Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        TimeText(
            // Curved
            textCurvedSeparator = {
                curvedColumn(modifier = CurvedModifier.angularSize(curvedSeparatorGap)) {}
                curvedText("·", style = CurvedTextStyle(textStyle))
                curvedColumn(modifier = CurvedModifier.angularSize(curvedSeparatorGap)) {}
            },
            startCurvedContent = {
                curvedRow(
                    modifier =
                        CurvedModifier.sizeIn(
                            maxSweepDegrees =
                                (curvedAnimatedSweep - curvedSeparatorSweep).coerceAtLeast(0f)
                        )
                ) {
                    curvedText(
                        text,
                        CurvedModifier.sizeIn(maxSweepDegrees = curvedTextSweep),
                        style = CurvedTextStyle(textStyle),
                        overflow = TextOverflow.Ellipsis,
                    )
                }
            },
            // Linear
            textLinearSeparator = {
                Spacer(modifier = Modifier.width(linearSeparatorGap))
                Text("·", style = textStyle)
                Spacer(modifier = Modifier.width(linearSeparatorGap))
            },
            startLinearContent = {
                Box(
                    modifier =
                        Modifier.clipToBounds()
                            .widthIn(
                                max = (linearAnimatedSize - linearSeparatorSize).coerceAtLeast(0.dp)
                            )
                ) {
                    Text(
                        text,
                        maxLines = 1,
                        style = textStyle,
                        modifier =
                            Modifier.wrapContentWidth(align = Alignment.Start, unbounded = true)
                                .widthIn(max = linearTextSize),
                        overflow = TextOverflow.Ellipsis,
                    )
                }
            },
        )
        Button(onClick = { showState = !showState }) { Text("Go!") }
    }
}
Jetpack Compose beyond MaterialFree components, screens and templates for apps that don’t look like Google’s. Copy them into your app, or let your coding agent add them.Browse for free

Content updated: