16

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?

2
  • 2
    You would need to create an AnnotatedString. I am not aware of any existing HTML->AnnotatedString converter libraries at this time, though I am sure that somebody will eventually create one. Commented Jun 22, 2021 at 15:03
  • 1
    Maybe this library can suit your needs. Commented Jun 22, 2021 at 16:58

5 Answers 5

8

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))
        }
    })
}
Sign up to request clarification or add additional context in comments.

Comments

3

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.

3 Comments

I'm going to accept this answer, since it seems like those are the only options for now.
@Stephan Yup, It is all we have as of now... Thanks.
HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY)
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/

Comments

3

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
            }
        }
    )
}

2 Comments

I copied your ExpandingText into a new kt file but it does not work for me. Sample HTML in this topic stackoverflow.com/questions/72736497/… The "team" is not link and click does not open browser.
With this you loose the visual text attributes like bold, italic, colors, etc.
2

There is now an official way since version 1.7.0 of library androidx.compose.ui:ui

Here is a simple example:

Text(AnnotatedString.fromHtml("<b>Bold</b> text"))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.