Question

Display HTML Styled Text in an Android TextView

htmlandroidxml-parsingtextview

Question

How can I display this HTML as styled text in an Android TextView?

<h2>Title</h2><br>
<p>description here</p>

I want the heading, line break, and paragraph formatting to appear in the TextView rather than showing the HTML tags as plain text.

Short Answer

Android TextView does not act like a web browser, so it cannot render arbitrary HTML and CSS. However, you can convert a supported subset of HTML into a Spanned object with HtmlCompat.fromHtml() and set that result as the text. You will also learn the limits of this approach, how to choose line-break behavior, and when a WebView is more appropriate.

Concept

A TextView displays text, including styled text such as bold, italic, links, colors, and relative font sizes. Android represents this styling with spans: formatting objects attached to ranges of characters.

HTML conversion utilities translate supported HTML tags into those spans. For example:

  • <b> or <strong> can become bold text.
  • <i> or <em> can become italic text.
  • <a> can become a clickable link when link handling is enabled.
  • <br> and <p> can become line breaks.

The result is a Spanned, which can be passed directly to TextView.setText().

This is useful when an app receives short, trusted, formatted content from resources, a CMS, or an API. It is not a full HTML renderer: CSS, JavaScript, complex layouts, and many browser features are not supported. For complete web content, use a WebView only when that is genuinely needed.

Mental Model

Think of a TextView as a printed note, not a miniature browser.

HTML is an instruction sheet that says, “make these characters bold” or “start a new line here.” HtmlCompat.fromHtml() reads the instruction sheet and adds formatting markers to the text. The TextView can then display those markers.

If the instruction says something the TextView does not understand, such as a complex CSS layout, it cannot reproduce it like a browser would.

Take Quiz

Syntax and Examples

Use AndroidX HtmlCompat to convert HTML into styled text.

import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.HtmlCompat;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView descriptionText = findViewById(R.id.descriptionText);

        String html = "<h2>Title</h2><br><p>description here</p>";

        descriptionText.setText(
                HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_COMPACT)
        );
    }
}

HtmlCompat.fromHtml() returns a Spanned value. A Spanned is text with formatting information attached to it, so TextView can display the converted formatting.

Use FROM_HTML_MODE_COMPACT when you want more compact paragraph spacing. Use FROM_HTML_MODE_LEGACY when you want behavior closer to older Android versions, which may insert more blank lines between block elements.

A minimal layout for the example is:

<TextView
    android:id="@+id/descriptionText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="16sp" />

Step by Step Execution

Consider this code:

String html = "<b>Important:</b> Read the <i>instructions</i>.<br>Thank you.";

Spanned styledText = HtmlCompat.fromHtml(
        html,
        HtmlCompat.FROM_HTML_MODE_COMPACT
);

textView.setText(styledText);
  1. html stores ordinary Java text that contains HTML tags.
  2. HtmlCompat.fromHtml(...) reads the supported tags.
  3. The converter removes the literal tags from the displayed result and creates formatting spans:
    • Important: receives a bold span.
    • instructions receives an italic span.
    • <br> becomes a line break.
  4. styledText holds both the visible characters and their formatting.
  5. textView.setText(styledText) displays the formatted result:
Important: Read the instructions.
Thank you.

The first word is bold and instructions is italic.

Real World Use Cases

Common uses for HTML-styled TextView content include:

  • Terms and notices: Show a short message with emphasis and links, such as “By continuing, you accept the Terms.”
  • CMS content: Display short article excerpts or announcements retrieved from an API.
  • Server-provided messages: Format maintenance notices, account messages, or promotional copy.
  • Localized strings: Keep small pieces of bold or italic formatting in string resources.
  • Email-like previews: Render a limited, safe subset of rich text without building a custom span for every piece of formatting.

For long articles with custom fonts, responsive images, tables, complex CSS, or embedded media, HTML conversion in a TextView is usually not enough.

Take Quiz

Real Codebase Usage

In production Android apps, developers often keep conversion in a small helper method so HTML parsing is consistent across screens.

import android.text.Spanned;
import androidx.core.text.HtmlCompat;

public final class HtmlText {
    private HtmlText() {
    }

    public static Spanned parse(String html) {
        String safeHtml = html == null ? "" : html;
        return HtmlCompat.fromHtml(
                safeHtml,
                HtmlCompat.FROM_HTML_MODE_COMPACT
        );
    }
}

Usage:

textView.setText(HtmlText.parse(apiResponse.getDescription()));

Useful project patterns include:

  • Null handling: Convert a missing API field to an empty string before parsing.
  • Content validation: Treat server HTML as content that must be reviewed or sanitized, especially if it can contain links or images.
  • Resource formatting: Put stable formatted text in strings.xml, then convert it after reading the resource.
  • Link handling: Set LinkMovementMethod only when you deliberately want HTML links to be tappable.
import android.text.method.LinkMovementMethod;

textView.setText(HtmlText.parse("Visit <a href=\"https://developer.android.com\">Android Developers</a>."));
textView.setMovementMethod(LinkMovementMethod.getInstance());

Clickable links can change touch behavior, so use them intentionally and test accessibility and scrolling behavior.

Common Mistakes

Passing the HTML string directly

This displays the tags as characters because no conversion happens.

// Incorrect for HTML formatting
textView.setText("<b>Warning</b>");

Convert it first:

textView.setText(HtmlCompat.fromHtml(
        "<b>Warning</b>",
        HtmlCompat.FROM_HTML_MODE_COMPACT
));

Expecting browser-level HTML and CSS

This may not look like it does in a browser:

<div style="display:flex; color: purple; padding: 20px;">Hello</div>

TextView HTML parsing supports only a limited subset of tags and attributes. Do not rely on complex CSS, layout rules, JavaScript, or arbitrary HTML features.

Using Html.fromHtml() without considering Android versions

Framework overloads differ across Android API levels. HtmlCompat.fromHtml() provides one consistent call style for AndroidX projects.

Assuming links are automatically clickable

An <a> tag can be converted into a link span, but tapping it generally requires a movement method:

textView.setMovementMethod(LinkMovementMethod.getInstance());

Creating unnecessary extra line breaks

<p> already represents a block of text. Combining several <br> tags and paragraphs can create more vertical space than expected. Prefer semantic tags and test both COMPACT and LEGACY modes.

Treating untrusted HTML as harmless

HTML from users or external systems can contain unexpected links, images, or misleading formatting. Limit what content is accepted, sanitize it on a trusted backend when appropriate, and avoid using this technique as a replacement for a security policy.

Comparisons

OptionBest forImportant limitation
HtmlCompat.fromHtml() + TextViewShort, simple formatted textSupports only a subset of HTML; no full CSS layout
SpannableStringFormatting fully controlled by your appMore code when content has many styles
WebViewFull web pages, CSS, JavaScript, complex HTMLHeavier component with additional security and lifecycle considerations
Plain TextView.setText(String)Unformatted labels and messagesHTML tags appear as normal text

HtmlCompat is usually the best middle ground for a small amount of basic rich text. Use SpannableString when the app owns the formatting, and consider a WebView only for actual web-like documents.

Take Quiz

Cheat Sheet

import androidx.core.text.HtmlCompat;

Spanned text = HtmlCompat.fromHtml(
        html,
        HtmlCompat.FROM_HTML_MODE_COMPACT
);
textView.setText(text);
  • TextView does not render raw HTML by itself.
  • HtmlCompat.fromHtml() converts supported HTML to Spanned text.
  • Use FROM_HTML_MODE_COMPACT for tighter block spacing.
  • Use FROM_HTML_MODE_LEGACY for older-style block spacing.
  • Use LinkMovementMethod.getInstance() if converted <a> links should be tappable.
  • Expect only limited HTML support; do not expect full CSS or JavaScript.
  • Handle nullable HTML before parsing:
String safeHtml = html == null ? "" : html;
  • Use a WebView only when the content requires browser-like rendering.

FAQ

Can a TextView display HTML directly?

Not directly. Pass the HTML through HtmlCompat.fromHtml() first, then set the returned Spanned on the TextView.

Which HTML tags does Android TextView support?

It supports a limited subset of common text-formatting tags. Support is not equivalent to a browser, so test the exact tags and attributes your content uses.

Why are my HTML tags showing as text?

You likely passed the raw string to setText(). Convert it with HtmlCompat.fromHtml() first.

How do I make HTML links clickable in a TextView?

After setting the converted text, call textView.setMovementMethod(LinkMovementMethod.getInstance()).

Should I use Html.fromHtml() or HtmlCompat.fromHtml()?

In an AndroidX app, HtmlCompat.fromHtml() is generally convenient because it offers a consistent API across Android versions.

Can I use CSS styles in TextView HTML?

Do not depend on CSS for styling or layout. The HTML parser is limited and does not provide browser-level CSS support.

Why do paragraphs have unexpected blank lines?

Block tags such as <p> add line breaks. Try FROM_HTML_MODE_COMPACT and avoid adding redundant <br> tags.

When should I use a WebView instead?

Use one when you need a full HTML document, substantial CSS styling, tables, embedded web content, or JavaScript.

Take Quiz

Mini Project

Description

Build a small announcement view that receives a title and message as HTML, renders the supported formatting in a TextView, and makes a documentation link tappable. This resembles an in-app notice supplied by a CMS or API.

Goal

Display a compact, formatted announcement with a clickable link in an Android TextView.

Requirements

Use a TextView in the layout. Convert an HTML string with HtmlCompat.fromHtml(). Use compact HTML line-break behavior. Include bold text, italic text, and one link. Make the link tappable with a movement method.

Take Quiz

Keep learning

Related questions

View more