Alexander Karkossa
10/25/2020, 8:22 AMAnnotatedString
is what u are looking for. When the html tagged String is comming from resources (with resources.getText
, not resources.getString
), u could use these method.
fun CharSequence.toAnnotatedString(urlSpanStyle: SpanStyle): AnnotatedString {
return if (this is Spanned) {
AnnotatedString.Builder().apply {
append(toString())
val urlSpans = getSpans<URLSpan>()
val styleSpans = getSpans<StyleSpan>()
val underlineSpans = getSpans<UnderlineSpan>()
urlSpans.forEach { urlSpan ->
val start = getSpanStart(urlSpan)
val end = getSpanEnd(urlSpan)
addStyle(urlSpanStyle, start, end)
addStringAnnotation("url", urlSpan.url, start, end)
}
styleSpans.forEach { styleSpan ->
val start = getSpanStart(styleSpan)
val end = getSpanEnd(styleSpan)
when (styleSpan.style) {
Typeface.BOLD -> addStyle(SpanStyle(fontWeight = FontWeight.Bold), start, end)
Typeface.ITALIC -> addStyle(SpanStyle(fontStyle = FontStyle.Italic), start, end)
Typeface.BOLD_ITALIC -> addStyle(SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic), start, end)
}
}
underlineSpans.forEach { underlineSpan ->
val start = getSpanStart(underlineSpan)
val end = getSpanEnd(underlineSpan)
addStyle(SpanStyle(textDecoration = TextDecoration.Underline), start, end)
}
}.toAnnotatedString()
} else {
AnnotatedString(text = toString())
}
}
You onle have to figure out, how to transfrom yout html tagged String from API to an SpannableString
oder SpannendString
.
Makeing the string visible in compose:
@Composable
fun HtmlText(
modifier: Modifier = Modifier,
@StringRes textId: Int,
urlSpanStyle: SpanStyle = SpanStyle(
color = MaterialTheme.colors.secondary,
textDecoration = TextDecoration.Underline),
textAlign: TextAlign = TextAlign.Start
) {
val context = ContextAmbient.current
val annotatedString = context.resources.getText(textId).toAnnotatedString(urlSpanStyle)
val uriHandler = UriHandlerAmbient.current
val layoutResult = remember { mutableStateOf<TextLayoutResult?>(null) }
Text(
modifier = modifier.tapGestureFilter { pos ->
layoutResult.value?.let { layoutResult ->
val position = layoutResult.getOffsetForPosition(pos)
annotatedString.getStringAnnotations(position, position)
.firstOrNull()
?.let { sa ->
if (sa.tag == "url") {
uriHandler.openUri(sa.item)
}
}
}
},
onTextLayout = { layoutResult.value = it },
text = annotatedString,
textAlign = textAlign
)
}
Hope this will help