How can I get the font size of a text when I use Text() in Compose?

Viewed 98

I create a new project by Empty Compose Activity wizard in Android Studio.

The Code A is generated code by Android Studio.

Text(text = "Hello $name!") displays a text with default font style, I hope to get the size and unit of the text, such as 16sp, where can I find these informations?

Code A

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {               
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Greeting("Android")
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

@Composable
fun MyApplicationTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}
3 Answers

You can check it here.
https://developer.android.com/jetpack/compose/text

Change text size and font style

Text("Hello World", fontSize = 30.sp,fontStyle = FontStyle.Italic)

Text has a fontFamily parameter to allow setting the font used in the composable. By default, serif, sans-serif, monospace and cursive font families are included.

You can use the TextLayoutResult to get the front style
The font style is in TextLayoutInput -> TextStyle

Text("Hello World", 
        onTextLayout = { result: TextLayoutResult ->
             Log.d(TAG, "FrontSize: "+ result.layoutInput.style.fontSize)
             Log.d(TAG, "FrontStyle: "+ result.layoutInput.style.toString())
    })

If you are using default theme it's in

MaterialTheme(
    colorScheme = colorScheme,
    typography = Typography,
    content = content
)

// Set of Material typography styles to start with
val Typography = Typography(
    bodyLarge = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        // HERE
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.5.sp
    )
    /* Other default text styles to override
    titleLarge = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 22.sp,
        lineHeight = 28.sp,
        letterSpacing = 0.sp
    ),
    labelSmall = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Medium,
        fontSize = 11.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.5.sp
    )
    */
)

However, if you apply any other theme or get Text from another library can get size of your text using onTextLayout callback which returns a lot of data about your text.

Without removing default padding on top or bottom of your font size won't be able to get correct height in sp. You get the height of Text in sp with the method below. I tried using LineHeightStyle Api also need to check lineHeight either for correct results.

Column {
    var heightInPx by remember { mutableStateOf(0f) }
    var info by remember { mutableStateOf("") }
    val heightInSp = LocalDensity.current.run { heightInPx.toSp() }
    Text("Hello World",
        modifier = Modifier
            .border(1.dp, Color.Green)
            .fillMaxWidth(),
        style = TextStyle(
            fontSize = 40.sp,
            platformStyle = PlatformTextStyle(
                includeFontPadding = false
            ),
            lineHeightStyle = LineHeightStyle(
                alignment = LineHeightStyle.Alignment.Top,
                trim = LineHeightStyle.Trim.Both
            )
        ),
        onTextLayout = { result: TextLayoutResult ->
            val cursorRect = result.getCursorRect(0)

            info = "firstBaseline: ${result.firstBaseline}, " +
                    "lastBaseline: ${result.lastBaseline}\n" +
                    "cursorRect: $cursorRect\n" +
                    "getLineBottom: ${result.getLineBottom(0)}, " +
                    "getBoundingBox: ${result.getBoundingBox(0)}"
            heightInPx =
                result.size.height.toFloat()
        }
    )

    Text("Height in px: $heightInPx, height in sp: $heightInSp")
    Text(info)
}

As you can see in the Text composable source code, when you explicitly don't specify fontSize or style (which you don't), it takes font size from the default style, which is LocalTextStyle.current.
Now LocalTextStyle can contain different styles throughout your code, you can override it yourself by doing something like this:

CompositionLocalProvider(LocalTextStyle provides TextStyle(...)) {
    Text() // will use specified TextStyle
}

A lot of material components do this, for example TopAppBar and Button, so you don't have to care about anything and correct style will always be used.
Finally, your style comes from the MaterialTheme composable, where is this piece of code:

ProvideTextStyle(value = typography.body1) {
    content()
}

So your font size comes from the Typography.body1 text style.

Related