Blog Infos
Author
Published
Topics
Published
Topics

The reason for writing this article is that Text composable function does not support HTML yet. Since there are plenty of utility libraries that try to archive the same, I chose the way of my implementation as it’s flexible and adjustable to my needs.

Requirements. I need:

  1. Fonts support.
  2. Text styling.
  3. Links support! This is especially important for me since my app is using in-app web-viewer to display any links.

Let’s see how each of the points archived. To make things clear — at high level this is just a wrapper for Android view. Full gist for this article.

The entrance

Start fromHtmlText.kt. For now, read as least the method signature:

@Composable
fun HtmlText(
    modifier: Modifier = Modifier,    
    html: String,
    textStyle: TextStyle = Typography.body1,
    onLink1Clicked: (() -> Unit)? = null,
    onLink2Clicked: (() -> Unit)? = null
)
Fonts support

Refer to TypefaceSpanCompat.kt in the gist.

In HtmlText.kt pay attention to these lines:

val fontResId = when (textStyle.fontWeight) {
    FontWeight.Medium -> R.font.inter_medium
    else -> R.font.inter_regular
}
val font = ResourcesCompat.getFont(context, fontResId)

How to connect TypefaceSpanCompat.kt with HtmlText.kt will be explained a bit later.

Text styling

By default HtmlText composable takes body1 TextStyle:

textStyle: TextStyle = Typography.body1,

And then maps it to classical Android parameters. As an example let’s look to the Gravity:

val gravity = when (textStyle.textAlign) {
    TextAlign.Center -> Gravity.CENTER
    TextAlign.End -> Gravity.END
    else -> Gravity.START
}

TextStyle can be easily modified. Example:

HtmlText(
    html = stringResource(id = R.string.create_drive),
    textStyle = Typography.body1.copy(textAlign = TextAlign.Center, color = Secondary),
    onLink1Clicked = onLearnMoreClicked
)
Links support

In HtmlText there are the next lines:

movementMethod = DefaultLinkMovementMethod() { link ->
    when (link) {
       LINK_1 -> onLink1Clicked?.invoke()
       LINK_2 -> onLink2Clicked?.invoke()                   
    }
    true
}

What is DefaultLinkMovementMethod? This is a java class copy-pasted from Stackoverflow that just changes spans under the hood to make onLinkClick methods possible. You may read the whole code here.

Links styling

Another thing is links styling. In HtmlText you may see this line:

setLinkTextColor(Primary.toArgb())

Another things is links underline. My design requires it to be removed. Refer to Spannable.removeLinksUnderline below.

Combining everything together

In HtmlText there is a line:

update = { it.text = fromHtml(it.context, html) },

Where fromHtml is a custom method. Let’s look at it here.

At first, it takes a string and makes a Spannable from it:

private fun parse(html: String): Spannable =                                             (HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT) as Spannable)

And then several Spannable transformations are made:

  1. Links underlines are removed in Spannable.removeLinksUnderline()
  2. Spannable.styleBold(context: Context) :
  • makes bold parts black (the default text for my HtmlText composables is gray but I want the bold parts to be black);
  • sets a dedicated font for the bold parts.
strings.xml

Finally, it’s important to show how I declare strings. This is a regular string with HTML (no links):

<string name="view_recovery_description">
    <![CDATA[
    <b>For your eyes only!</b> Anyone who has access to your 12 word recovery phrase can access your entire wallet. Learn more
    ]]>
</string>

And this is the same text but with the link:

<string name="view_recovery_description">
    <![CDATA[
    <b>For your eyes only!</b> Anyone who has access to your 12 word recovery phrase can access your entire wallet. <a href="link_1">Learn more</a>
    ]]>
</string>

As you see, I’m using link_1 and link_2 hrefs to declare a link. Later, in a callback I can do whenever I want. In my case, I open a build-in browser page to handle it.

Job Offers

Job Offers


    Senior Android Engineer

    Carly Solutions GmbH
    Munich
    • Full Time
    apply now

    Senior Android Developer

    SumUp
    Berlin
    • Full Time
    apply now

OUR VIDEO RECOMMENDATION

, ,

Boosting Compose UI from Sluggish to Snappy

Join us on an enlightening quest as we unravel the realm of Compose UI performance. With a multitude of tools at our disposal, the challenge lies in knowing where to start and how to choose.
Watch Video

Boosting Compose UI from Sluggish to Snappy

Akshay Chordiya & Tasha Ramesh
Android Developer & Android
Tinder

Boosting Compose UI from Sluggish to Snappy

Akshay Chordiya & ...
Android Developer & ...
Tinder

Boosting Compose UI from Sluggish to Snappy

Akshay Chordiya ...
Android Developer & Andro ...
Tinder

Jobs

Visual example

That’s it! With ~100 lines of code we are now able to display almost any HTML. Let’s look at the example:

String for this example:

<string name="create_drive_pass_description">
    <![CDATA[
    This password protects your Google Drive backups. <b>Store this password somewhere safe.</b> We cannot recover your password for you. <a href="link_1">Learn more</a>
    ]]>
</string>

Code:

HtmlText(
    modifier = Modifier.padding(top = SIZE_16, bottom = SIZE_32),
    html = stringResource(id = R.string.create_drive_pass_description),
    textStyle = Typography.body1.copy(textAlign = TextAlign.Center, color = Secondary),
    onLink1Clicked = onLearnMoreClicked
)

That’s it! Thank you for reading.

You can support my work by clapping this article or sharing it.

 

This article was originally published on proandroiddev.com on June 27, 2022

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
Compose is a relatively young technology for writing declarative UI. Many developers don’t even…
READ MORE
blog
When it comes to the contentDescription-attribute, I’ve noticed a couple of things Android devs…
READ MORE
blog
In this article we’ll go through how to own a legacy code that is…
READ MORE
blog
Compose is part of the Jetpack Library released by Android last spring. Create Android…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu