Nat Strangerweather

    Nat Strangerweather

    1 year ago
    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:
    val convertedString = textState.value.text.splitToSequence(' ')
            .filter { it.isNotBlank() }
            .toList()
    But I can't find how to differentiate the words to decorate them differently:
    Text(textState.value.text,  style = TextStyle(color = listOfColors.random()))
    jossiwolf

    jossiwolf

    1 year ago
    You probably want to be using an
    AnnotatedString
    🙂 https://developer.android.com/jetpack/compose/text#multiple-styles
    Nat Strangerweather

    Nat Strangerweather

    1 year ago
    Aha! This looks interesting, many thanks!
    The problem though is that all the examples are with hardcoded text. What if I wanted to give a different colour to each word that the user inputs into the TextField, like for a word cloud? Something like this:
    m

    Mark Murphy

    1 year ago
    @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.
    Nat Strangerweather

    Nat Strangerweather

    1 year ago
    Thanks, I tried this:
    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

    Mark Murphy

    1 year ago
    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:
    @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)
    }
    Nat Strangerweather

    Nat Strangerweather

    1 year ago
    Fabulous, thank you so much! 🙂