Viktor Isacenko
Viktor Isacenko

Reputation: 173

Multiple colors in TextField of Jetpack Compose

Is it possible to get different colors in a TextField of Jetpack Compose?

Something like with the Text composable with AnnotatedString, but TextField doesn't allow AnnotatedString as input value.

Image of normal Text composable with colors

enter image description here

Upvotes: 17

Views: 6248

Answers (3)

noe
noe

Reputation: 2107

TextField directly supports AnnotatedString if you use the version that uses TextFieldValue instead of plain strings (see the docs).

The annotated string is contained inside the TextFieldValue, in the annotatedString property (see docs), together with the selection and the composition ranges.

UPDATE: there is an open bug that makes the TextField lose the formatting info as soon as it gets the focus, so don't use this approach just yet.

Upvotes: 0

Youn Tivoli
Youn Tivoli

Reputation: 300

depending on Gabriele Mariotti answer, if you had trouble in inherit VisualTransformation class you can use TransformedText directly in the TextField.

TextField(
    value = text,
    onValueChange = { text = it },
    visualTransformation = {
        TransformedText(
            buildAnnotatedStringWithColors(text),
            OffsetMapping.Identity
        )
    }
)


fun buildAnnotatedStringWithColors(text:String): AnnotatedString{ ... }

Upvotes: 0

Gabriele Mariotti
Gabriele Mariotti

Reputation: 365028

You can use the VisualTransformation in the TextField.

TextField(
    value = text,
    onValueChange = { text = it },
    visualTransformation = ColorsTransformation()
)

In the VisualTransformation you can use AnnotatedString to display the text with multiple styles.

Something like:

class ColorsTransformation() : VisualTransformation {
    override fun filter(text: AnnotatedString): TransformedText {
        return TransformedText(
            buildAnnotatedStringWithColors(text.toString()), 
            OffsetMapping.Identity)
    }
}

with:

fun buildAnnotatedStringWithColors(text:String): AnnotatedString{
    val words: List<String> = text.split("\\s+".toRegex())// splits by whitespace
    val colors = listOf(Color.Red,Color.Black,Color.Yellow,Color.Blue)
    var count = 0

    val builder = AnnotatedString.Builder()
    for (word in words) {
        builder.withStyle(style = SpanStyle(color = colors[count%4])) {
            append("$word ")
        }
        count ++
    }
    return builder.toAnnotatedString()
}

enter image description here

Upvotes: 29

Related Questions