Как выделить конкретное слово в тексте в составе джетпака?
Я хотел знать, как выделить определенную часть текста в компоновке реактивного ранца. Я пытался
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
}