'Jetpack compose display html in text

I have a string that contains html, how can I display this in a Jetpack compose Text?

In a TextView I would use a Spanned and do something like:

TextView.setText(Html.fromHtml("<p>something", HtmlCompat.FROM_HTML_MODE_LEGACY)

How can I do this with Text from Jetpack compose?



Solution 1:[1]

Unfortunately, Jetpack compose does NOT support HTML yet...

So, what you could do is:

Option 1: Create your own HTML parser

Jetpack compose supports basic styling such as Bold, color, font etc.. So what you can do is loop through the original HTML text and apply text style manually.

Option 2: Integrate the old TextView into your Jetpack compose.

Please read: Adopting Compose in your app

Thanks.

Solution 2:[2]

Same answer as Yhondri, but using HtmlCompat if you are targeting api >24:

@Composable
fun Html(text: String) {
    AndroidView(factory = { context ->
        TextView(context).apply {
            setText(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY))
        }
    })
}

Solution 3:[3]

You can integrate the old TextView into your Jetpack compose like follows:

AndroidView(factory = { context ->
                    TextView(context).apply {
                        text = Html.fromHtml(your_html)
                    }
                })

More info: https://foso.github.io/Jetpack-Compose-Playground/viewinterop/androidview/

Solution 4:[4]

I have done it this way instead of using TextView in AndroidView and it seems to work quite well for me. The below composable also wraps up the text and expands when you click on it.

@Composable
fun ExpandingText(
    description: String,
    modifier: Modifier = Modifier,
    textStyle: TextStyle = MaterialTheme.typography.body2,
    expandable: Boolean = true,
    collapsedMaxLines: Int = 3,
    expandedMaxLines: Int = Int.MAX_VALUE,
) {
    val text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        Html.fromHtml(description, Html.FROM_HTML_MODE_LEGACY)
    } else {
        HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_LEGACY)
    }

    var canTextExpand by remember(text) { mutableStateOf(true) }
    var expanded by remember { mutableStateOf(false) }
    val interactionSource = remember { MutableInteractionSource() }

    Text(
        text = text.toString(),
        style = textStyle,
        overflow = TextOverflow.Ellipsis,
        maxLines = if (expanded) expandedMaxLines else collapsedMaxLines,
        modifier = Modifier
            .clickable(
                enabled = expandable && canTextExpand,
                onClick = { expanded = !expanded },
                indication = rememberRipple(bounded = true),
                interactionSource = interactionSource,
            )
            .animateContentSize(animationSpec = spring())
            .then(modifier),
        onTextLayout = {
            if (!expanded) {
                canTextExpand = it.hasVisualOverflow
            }
        }
    )
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 minchaej
Solution 2 Dambakk
Solution 3 Yhondri
Solution 4 Akram Hussain