Monospace numbers in the Jetpack Compose Text component
Asked Answered
S

4

6

I'm using a custom font within my Jetpack Compose app and would like to monospace the numbers within a specific Text component.

With standard Android TextView, this can be done using the fontFeatureSetting="tnum" attribute (https://mcmap.net/q/638054/-monospace-tabular-numbers-in-android-textviews).

How can you do this with Jetpack Compose?

Countdown clock

Salic answered 31/8, 2021 at 0:49 Comment(0)
L
9

buildAnnotatedString is needed to customize different parts of a string.

If you need to apply some text style to the whole Text, you can use style argument.

Text(
    text = String.format(Locale.ROOT, "%02d:%02d", mins, secs),
    style = LocalTextStyle.current.copy(fontFeatureSettings = "tnum"),
)

I'm using LocalTextStyle.current here, which is the default style for Text, but you can replace it with the one you need, like one of your theme typography: MaterialTheme.typography.h4

Labret answered 31/8, 2021 at 8:8 Comment(1)
Yep, this is better. Thanks Phillip!Salic
S
3

This can be done using an annotated string and SpanStyle.

    Text(
        text = buildAnnotatedString {
            withStyle(style = SpanStyle(fontFeatureSettings = "tnum")) {
                append(String.format(Locale.ROOT, "%02d:%02d", mins, secs))
            }
        }
    )

By default, numbers are displayed using the propotional-nums setting which allows the number to take only as much space as it needs. tabular-num or tnum forces all numbers to take up the same amount of space for the given font size. This allow you to render numbers in a monospaced-like format which is useful for views that update the numbers or for a table-like view that displays numbers.

The result is a view that will take up the same amount of space no matter the number displayed in it:

enter image description here

Salic answered 31/8, 2021 at 0:49 Comment(1)
Awesome. Too bad it didn't work for hexadecimal numbers as well.Declassify
S
1

This works for me

val fontFamily = FontFamily(Typeface(android.graphics.Typeface.MONOSPACE))
buildAnnotatedString.addStyle(SpanStyle(fontFamily = fontFamily), start, end)
Supreme answered 12/1, 2023 at 10:55 Comment(0)
S
0
val textStyle = TextStyle(
    fontSize = textWithoutScale(size = 26f),
    color = gray900,
    fontWeight = FontWeight.Normal,
    textAlign = TextAlign.Start,
    letterSpacing = 7.sp,
    fontFamily = FontFamily(Typeface.MONOSPACE) //Here's the magic!
)
Sidelight answered 1/2, 2023 at 18:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.