Как выделить конкретное слово в тексте в составе джетпака?

Я хотел знать, как выделить определенную часть текста в компоновке реактивного ранца. Я пытался Html.fromHtml() как это

      Text(text = Html.fromHtml(" <font color='red'> Hello </font> World").toString())

Но это не сработало. Есть ли способ сделать это в сочинении?

4 ответа

Решение

С участием 1.0.0-beta03 вы можете использовать AnnotatedString для отображения текста с несколькими стилями.

Что-то вроде:

      Text(buildAnnotatedString {
    withStyle(style = SpanStyle(color = Color.Red)) {
        append("Hello")
    }
    append(" World ")
})

Вы можете использовать AnnotatedString для добавления каждого слова/раздела с его собственным стилем или для добавления другого стиля в любой индекс, что отлично, если вы используете строковый ресурс.

Для примера hello world вы можете построить что-то вроде этого:

      
val annotatedString = buildAnnotatedString {
    val str = "Hello World" // or stringResource(id = R.string.hello_world)
    val boldStr = "Hello" // or stringResource(id = R.string.hello)
    val startIndex = str.indexOf(boldStr)
    val endIndex = startIndex + boldStr.length
    append(str)
    addStyle(style = SpanStyle(color = Color.Red), start = startIndex, end = endIndex)
}
Text(
    text = annotatedString,
)

С использованиемaddStyleтаким образом позволяет нам делать некоторые забавные вещи, такие как добавление нескольких стилей к одному и тому же тексту.

      val annotatedString = buildAnnotatedString {
    val str = "Hello Wonderful World" // or stringResource(id = R.string.hello_world)
    val boldStr = "Wonderful World" // or stringResource(id = R.string.world)
    val startIndex = str.indexOf(boldStr)
    val endIndex = startIndex + boldStr.length
    append(str)
    addStyle(style = SpanStyle(color = Color.Red), start = startIndex, end = endIndex)

    val italicsStr = "Wonderful"
    val italicsStartIndex = str.indexOf(italicsStr)
    val italicsEndIndex = startIndex + italicsStr.length
    addStyle(style = SpanStyle(fontStyle = FontStyle.Italic), start = italicsStartIndex, end = italicsEndIndex)
}
Text(
    text = annotatedString,
    style = TextStyle(fontWeight = FontWeight.Bold),
    color = Color.Blue,
)

Проверьте эту функцию ниже. Здесь абзац — это ваш источник строки, а searchQuery — это конкретный текст, который вы хотите выделить.

Это обеспечивает динамическое состояние выделения текста и поиска.

      @Composable
    fun getData(): StateFlow<AnnotatedString?> {

        val span = SpanStyle(
            color = MaterialTheme.colorScheme.onPrimaryContainer,
            fontWeight = FontWeight.SemiBold,
            background = MaterialTheme.colorScheme.primaryContainer
        )

        return combine(paragraph, searchQuery) { text, query ->
            buildAnnotatedString {
                var start = 0
                while (text.indexOf(query, start, ignoreCase = true) != -1 && query.isNotBlank()) {
                    val firstIndex = text.indexOf(query, start, true)
                    val end = firstIndex + query.length
                    append(text.substring(start, firstIndex))
                    withStyle(style = span) {
                        append(text.substring(firstIndex, end))
                    }
                    start = end
                }
                append(text.substring(start, text.length))
                toAnnotatedString()
            }
        }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
    }

Вдохновлен ответом Мэтта Смита, но более многоразовым и гибким способом, используя список уточнений и (вместоPairэто может быть обычайdata classесли вам нужно что-то еще...)

Затем повторитеlistаннотироватьstringс соответствующимSpanStyleк ихplaceholder.

      @Composable
fun annotateRecursively(
    placeHolderList: List<Pair<String, SpanStyle>>,
    originalText: String
): AnnotatedString {
    var annotatedString = buildAnnotatedString { append(originalText) }
    for (item in placeHolderList) {
        annotatedString = buildAnnotatedString {
            val startIndex = annotatedString.indexOf(item.first)
            val endIndex = startIndex + item.first.length
            append(annotatedString)
            addStyle(style = item.second, start = startIndex, end = endIndex)
        }
    }
    return annotatedString
}
Другие вопросы по тегам