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.
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);
htmlstores ordinary Java text that contains HTML tags.HtmlCompat.fromHtml(...)reads the supported tags.- The converter removes the literal tags from the displayed result and creates formatting spans:
Important:receives a bold span.instructionsreceives an italic span.<br>becomes a line break.
styledTextholds both the visible characters and their formatting.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.
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
LinkMovementMethodonly 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
| Option | Best for | Important limitation |
|---|---|---|
HtmlCompat.fromHtml() + TextView | Short, simple formatted text | Supports only a subset of HTML; no full CSS layout |
SpannableString | Formatting fully controlled by your app | More code when content has many styles |
WebView | Full web pages, CSS, JavaScript, complex HTML | Heavier component with additional security and lifecycle considerations |
Plain TextView.setText(String) | Unformatted labels and messages | HTML 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.
Cheat Sheet
import androidx.core.text.HtmlCompat;
Spanned text = HtmlCompat.fromHtml(
html,
HtmlCompat.FROM_HTML_MODE_COMPACT
);
textView.setText(text);
TextViewdoes not render raw HTML by itself.HtmlCompat.fromHtml()converts supported HTML toSpannedtext.- Use
FROM_HTML_MODE_COMPACTfor tighter block spacing. - Use
FROM_HTML_MODE_LEGACYfor 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
WebViewonly 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.
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.
Keep learning
Related questions
Add a Favicon to a Static HTML Page
Learn how to add a favicon to static HTML pages, use correct paths and icon formats, and troubleshoot browser caching and local-file issues.
Allow Only Numeric Input (0-9) in HTML Input Using jQuery
Learn how to allow only digits 0-9 in an HTML input using jQuery, with examples, validation tips, common mistakes, and best practices.
Apply CSS !important with jQuery .css()
Learn why jQuery .css() cannot set !important and how to use CSSStyleDeclaration.setProperty() to apply inline important styles safely.