Is it possible to apply different styles (e.g. col...
# compose
n
Is it possible to apply different styles (e.g. colour) to each word of a given String? I have turned the String into a list of words like this:
Copy code
val convertedString = textState.value.text.splitToSequence(' ')
        .filter { it.isNotBlank() }
        .toList()
But I can't find how to differentiate the words to decorate them differently:
Copy code
Text(textState.value.text,  style = TextStyle(color = listOfColors.random()))
j
You probably want to be using an
AnnotatedString
๐Ÿ™‚ https://developer.android.com/jetpack/compose/text#multiple-styles
๐Ÿ™ 1
n
Aha! This looks interesting, many thanks!
๐Ÿ‘ 1
m
Copy code
@Preview
@Composable
fun ColorizedWords() {
  val wordsAndColors = listOf(
    "this is" to Color.Black,
    "an example" to Color.LightGray,
    "of iterating" to Color.Yellow,
    "through data" to Color.Blue,
    "to create" to Color.Magenta,
    "an AnnotatedString" to Color.DarkGray,
    "where pairs" to Color.Green,
    "of words" to Color.Cyan,
    "use different" to Color.Red,
    "Compose colors" to Color.Gray
  )

  val result = with(AnnotatedString.Builder()) {
    wordsAndColors.forEach { (word, color) ->
      pushStyle(SpanStyle(color = color))
      append(word)
      pop()
      append(" ")
    }

    toAnnotatedString()
  }

  Text(result)
}
Here, I use
AnnotatedString.Builder
to build an
AnnotatedString
built up from individual chunks with different colors.
๐Ÿ‘ 1
n
Thanks, I tried this:
Copy code
val wordsAndColors = listOf(textState.value.text to listOfColors.random())

    val result = with(AnnotatedString.Builder()) {
        wordsAndColors.forEach { (word, color) ->
            pushStyle(SpanStyle(color = color))
            append(word)
            pop()
            append(" ")
        }
        toAnnotatedString()
    }
But what happens is that the whole String changes to a new color every time a word is added to the textField. Whereas what I want is for each word to have a new color when added to the textField.
m
Your
wordsAndColors
is a single-element list. Based on your original question, you want several elements in the list. I do not know your real-world source of the text or your real-world algorithm for choosing a color. Here is a list of words, each word with a random color:
Copy code
@Preview
@Composable
fun ColorizedWords() {
  val colors = listOf(
    Color.Black,
    Color.LightGray,
    Color.Yellow,
    Color.Blue,
    Color.Magenta,
    Color.DarkGray,
    Color.Green,
    Color.Cyan,
    Color.Red,
    Color.Gray
  )
  val words = "From where the sun now stands, I shall fight no more forever."
    .split(" ")
  val wordsAndColors = words.associateWith { colors.random() }

  val result = with(AnnotatedString.Builder()) {
    wordsAndColors.forEach { (word, color) ->
      pushStyle(SpanStyle(color = color))
      append(word)
      pop()
      append(" ")
    }

    toAnnotatedString()
  }

  Text(result)
}
n
Fabulous, thank you so much! ๐Ÿ™‚
๐Ÿ‘๐Ÿป 1