share
Stack OverflowHow does Text("Hello") display font color when I use Jetpack Compose with default settings?
[+1] [3] HelloCW
[2022-08-28 02:05:45]
[ android android-jetpack-compose ]
[ https://stackoverflow.com/questions/73515525/how-does-texthello-display-font-color-when-i-use-jetpack-compose-with-defaul ]

I create a project with the wizard Empty Compose Activity of Android Studio. I use Text("Hello") to display a text.

I know the font size of the text is 16.sp by looking source code, but how can I know which color is displayed of the text?

BTW, I look at the source code , the color of font is specified as Color.Unspecified, I don't know what color will be displayed for Color.Unspecified.

Source Code

// Set of Material typography styles to start with
val Typography = Typography(
    body1 = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp
    )
    ...
)


class TextStyle
@OptIn(ExperimentalTextApi::class)
internal constructor(
    ...
) {
    ...
    @OptIn(ExperimentalTextApi::class)
    constructor(
        color: Color = Color.Unspecified,
        fontSize: TextUnit = TextUnit.Unspecified,
    ...
}


val Unspecified = Color(0f, 0f, 0f, 0f, ColorSpaces.Unspecified)
[+4] [2022-08-28 06:34:18] Gabriele Mariotti [ACCEPTED]

The color in the Text is defined by the color parameter or applying a TextStyle. The default value is Color.Unspecified [1].
If color = Color.Unspecified and style has no color set, this will be LocalContentColor [2] which provides a default Color.Black [3] color if not specified.

[1] https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Color.Companion#Unspecified()
[2] https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#LocalContentColor()
[3] https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Color.Companion#Black()

Thanks! I have searched the default color is Color.Black for LocalContentColor - HelloCW
I don't know why Android Studio need to design so complex architecture. If I do it, the default font color of Text is Color.Black and user can overwrite it. - HelloCW
1
[+2] [2022-08-28 03:56:30] Abhimanyu

If we look at the source code of Text composable, we can find,

val textColor = color.takeOrElse {
    style.color.takeOrElse {
        LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
    }
}
  1. Here color is the argument passed to the Text composable, which defaults to Color.Unspecified if no color is passed.

We see a method takeOrElse is used.

takeOrElse definition

inline fun Color.takeOrElse(block: () -> Color): Color = if (isSpecified) this else block()

Color.isSpecified definition

inline val Color.isSpecified: Boolean get() = value != Color.Unspecified.value

In other words, we can read this code as set textColor as the color if it is not equal to Color.Unspecified, else use the value in the given lambda.

Since we already know the color is Color.Unspecified if no color is specified (from above point 1), the value in the lambda will be used.

Value in lambda

The lambda checks if there is a color in the style TextStyle provided (either by user or by default value LocalTextStyle.current). If there is one, it will be used. Else the value of the below will be used.

LocalContentColor.current.copy(alpha = LocalContentAlpha.current)

LocalContentColor, LocalContentAlpha and LocalTextStyle are provided using CompositionLocalProvider.


Thanks! Where can I find the details about LocalTextStyle.current ? so I can know such as font size, font color, and so on. - HelloCW
All the local components LocalTextStyle, LocalContentColor, etc. vary according to their composable. If called from Button you might get a different value than when called from Scaffold body. The easiest way to determine the value is to either create a variable and use a debugger or log the values. - Abhimanyu
2
[+1] [2022-08-28 07:57:26] Thracian

As the other answers explain which color is interpreted when color is Color.Unspecified (which is LocalContentColor.current), I will answer why there is a Color.Unspecified instead of Color.Transparent

Because Color is an inline class, this represents an unset value without having to box [1] the Color object. It will be treated as Transparent when drawn. A Color object can be compared with Color.Unspecified for equality check, or the property isUnspecified of the object can be used to check for the unset value (or Color#isSpecified for any color that isn't Color.Unspecified).

This approach is used with Offset.Unspecified, Size.Unspecified and other classes that have an equivalent 'Unspecified' field for equality checks.

I don't know what color will be displayed for Color.Unspecified.

If you need to get the color dynamically at runtime, for example if you dynamically set colors and need them to change based on their current color you can use

Text("Hello World",
    onTextLayout = {
        it.layoutInput.style.color
    }
)

Which will return

enter image description here

And if you assign a Color

Text("Hello World",
    color = Color.Red,
    onTextLayout = {
        it.layoutInput.style.color
    }
)

enter image description here

[1] https://discuss.kotlinlang.org/t/autoboxing-done-right-how-by-using-to-functions/8927

3