822
votes

I have simple HTML:

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

I want to display HTML styled text it in TextView. How to do this?

26
Do you want to display the tags or omit them?DerMike
check out this link for working example javatechig.com/2013/04/07/how-to-display-html-in-android-viewNilanchal
If you are looking for deprecated's solution, it just right here stackoverflow.com/questions/37904739/…crgarridos
textview.setText(Html.fromHtml("your HTML")); is best method to show only HTML tags. also there is a method to play JS.Basudev Adhikary
Android does not support all the HTML tags. Check this arkapp.medium.com/android-set-html-in-text-view-b912e1a96b21 to understand better how to use in text view.abdul rehman

26 Answers

1468
votes

You need to use Html.fromHtml() to use HTML in your XML Strings. Simply referencing a String with HTML in your layout XML will not work.

This is what you should do in Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>", Html.FROM_HTML_MODE_COMPACT));
} else { 
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>"));
}

And in Kotlin:

textView.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT)
} else {
    Html.fromHtml(html)
}
84
votes

setText(Html.fromHtml(bodyData)) is deprecated after api 24. Now you have to do this:

 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
      tvDocument.setText(Html.fromHtml(bodyData,Html.FROM_HTML_MODE_LEGACY));
 } else {
      tvDocument.setText(Html.fromHtml(bodyData));
 }
71
votes

Have a look on this: https://stackoverflow.com/a/8558249/450148

It is pretty good too!!

<resource>
    <string name="your_string">This is an <u>underline</u> text demo for TextView.</string>
</resources>

It works only for few tags.

45
votes

If you want to be able to configure it through xml without any modification in java code you may find this idea helpful. Simply you call init from constructor and set the text as html

public class HTMLTextView extends TextView {
    ... constructors calling init...
    private void init(){
       setText(Html.fromHtml(getText().toString()));
    }    
}

xml:

<com.package.HTMLTextView
android:text="@string/about_item_1"/>
32
votes

If you are trying to show HTML from a string resource id, the formatting may not show up on screen. If that is happening to you, try using CDATA tags instead:

strings.xml:
<string name="sample_string"><![CDATA[<h2>Title</h2><br><p>Description here</p>]]></string>

...

MainActivity.java:
text.setText(Html.fromHtml(getString(R.string.sample_string));

See this post for further details.

25
votes

The below code gave best result for me.

TextView myTextview = (TextView) findViewById(R.id.my_text_view);
htmltext = <your html (markup) character>;
Spanned sp = Html.fromHtml(htmltext);
myTextview.setText(sp);
15
votes

I know this question is old. Other answers here suggesting Html.fromHtml() method. I suggest you to use HtmlCompat.fromHtml() from androidx.core.text.HtmlCompat package. As this is backward compatible version of Html class.

Sample code:

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

String htmlString = "<h1>Hello World!</h1>";

Spanned spanned = HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT);

TextView tvOutput = (TextView) findViewById(R.id.text_view_id);

tvOutput.setText(spanned);

By this way you can avoid Android API version check and it's easy to use (single line solution).

14
votes
String value = "<html> <a href=\"http://example.com/\">example.com</a> </html>";
    SiteLink= (TextView) findViewById(R.id.textViewSite);
    SiteLink.setText(Html.fromHtml(value));
    SiteLink.setMovementMethod(LinkMovementMethod.getInstance());
12
votes

If you just want to display some html text and don't really need a TextView, then take a WebView and use it like following:

String htmlText = ...;
webview.loadData(htmlText , "text/html; charset=UTF-8", null);

This does not restrict you to a few html tags either.

12
votes

The best approach to use CData sections for the string in strings.xml file to get a actual display of the html content to the TextView the below code snippet will give you the fair idea.

//in string.xml file
<string name="welcome_text"><![CDATA[<b>Welcome,</b> to the forthetyroprogrammers blog Logged in as:]]> %1$s.</string>

//and in Java code
String welcomStr=String.format(getString(R.string.welcome_text),username);
tvWelcomeUser.setText(Html.fromHtml(welcomStr));

CData section in string text keeps the html tag data intact even after formatting text using String.format method. So, Html.fromHtml(str) works fine and you’ll see the bold text in Welcome message.

Output:

Welcome, to your favorite music app store. Logged in as: username

10
votes

It's worth mentioning that the method Html.fromHtml(String source) is deprecated as of API level 24. If that's your target API, you should use Html.fromHtml(String source, int flags) instead.

8
votes

Created Kotlin extensions to convert html from String -

fun String?.toHtml(): Spanned? {
    if (this.isNullOrEmpty()) return null
    return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_COMPACT)
}
6
votes

I would like also to suggest following project: https://github.com/NightWhistler/HtmlSpanner

Usage is almost the same as default android converter:

(new HtmlSpanner()).fromHtml()

Found it after I already started by own implementation of html to spannable converter, because standard Html.fromHtml does not provide enough flexibility over rendering control and even no possibility to use custom fonts from ttf

5
votes

Simple use Html.fromHtml("html string"). This will work. If the string has tags like <h1> then spaces will come. But we cannot eliminate those spaces. If you still want to remove the spaces, then you can remove the tags in the string and then pass the string to the method Html.fromHtml("html string"); . Also generally these strings come from server(dynamic) but not often, if it is the case better to pass the string as it is to the method than try to remove the tags from the string.

5
votes

It has been suggested through various answers to use the Html framework class as suggested here, but unfortunately this class has different behavior in different versions of Android and various unaddressed bugs, as demonstrated in issues 214637, 14778, 235128 and 75953.

You may therefore want to use a compatibility library to standardize and backport the Html class across Android versions which includes more callbacks for elements and styling:

Github project HtmlCompat

While it is similar to the framework's Html class, some signature changes were required to allow more callbacks. Here's the sample from the GitHub page:

Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0);
// You may want to provide an ImageGetter, TagHandler and SpanCallback:
//Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0,
//        imageGetter, tagHandler, spanCallback);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(fromHtml);
4
votes

I have implemented this using web view. In my case i have to load image from URL along with the text in text view and this works for me.

WebView myWebView =new WebView(_context);
        String html = childText;
        String mime = "text/html";
        String encoding = "utf-8";
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.loadDataWithBaseURL(null, html, mime, encoding, null);
4
votes
String value = html value ....
mTextView.setText(Html.fromHtml(value),TextView.BufferType.SPANNABLE)
4
votes

Make a global method like:

public static Spanned stripHtml(String html) {
            if (!TextUtils.isEmpty(html)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    return Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT);
                } else {
                    return Html.fromHtml(html);
                }
            }
            return null;
        }

You can also use it in your Activity/Fragment like:

text_view.setText(stripHtml(htmlText));
2
votes

Whenever you write custom text view basic HTML set text feature will be get vanished form some of the devices.

So we need to do following addtional steps make is work

public class CustomTextView extends TextView {

    public CustomTextView(..) {
        // other instructions
        setText(Html.fromHtml(getText().toString()));
    }
}
1
votes
public class HtmlTextView extends AppCompatTextView {

public HtmlTextView(Context context) {
    super(context);
    init();
}

private void init(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        setText(Html.fromHtml(getText().toString(), Html.FROM_HTML_MODE_COMPACT));
    } else {
        setText(Html.fromHtml(getText().toString()));
    }
 }
}

update of answer above

1
votes

Use below code to get the solution:

textView.setText(fromHtml("<Your Html Text>"))

Utitilty Method

public static Spanned fromHtml(String text)
{
    Spanned result;
    if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        result = Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY);
    } else {
        result = Html.fromHtml(text);
    }
    return result;
}
1
votes

Simply use:

String variable="StackOverflow";
textView.setText(Html.fromHtml("<b>Hello : </b>"+ variable));
0
votes

May I suggest a somewhat hacky but still genius solution! I got the idea from this article and adapted it for Android. Basically you use a WebView and insert the HTML you want to show and edit in an editable div tag. This way when the user taps the WebView the keyboard appears and allows editing. They you just add some JavaScript to get back the edited HTML and voila!

Here is the code:

public class HtmlTextEditor extends WebView {

    class JsObject {
        // This field always keeps the latest edited text
        public String text;
        @JavascriptInterface
        public void textDidChange(String newText) {
            text = newText.replace("\n", "");
        }
    }

    private JsObject mJsObject;

    public HtmlTextEditor(Context context, AttributeSet attrs) {
        super(context, attrs);

        getSettings().setJavaScriptEnabled(true);
        mJsObject = new JsObject();
        addJavascriptInterface(mJsObject, "injectedObject");
        setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                loadUrl(
                        "javascript:(function() { " +
                            "    var editor = document.getElementById(\"editor\");" +
                            "    editor.addEventListener(\"input\", function() {" +
                            "        injectedObject.textDidChange(editor.innerHTML);" +
                            "    }, false)" +
                            "})()");
            }
        });
    }

    public void setText(String text) {
        if (text == null) { text = ""; }

        String editableHtmlTemplate = "<!DOCTYPE html>" + "<html>" + "<head>" + "<meta name=\"viewport\" content=\"initial-scale=1.0\" />" + "</head>" + "<body>" + "<div id=\"editor\" contenteditable=\"true\">___REPLACE___</div>" + "</body>" + "</html>";
        String editableHtml = editableHtmlTemplate.replace("___REPLACE___", text);
        loadData(editableHtml, "text/html; charset=utf-8", "UTF-8");
        // Init the text field in case it's read without editing the text before
        mJsObject.text = text;
    }

    public String getText() {
        return mJsObject.text;
    }
}

And here is the component as a Gist.

Note: I didn't need the height change callback from the original solution so that's missing here but you can easily add it if needed.

0
votes

You can use simple Kotlin extension function like this:

fun TextView.setHtmlText(source: String) {
    this.text = HtmlCompat.fromHtml(source, HtmlCompat.FROM_HTML_MODE_LEGACY)
}

And usage:

textViewMessage.setHtmlText("Message: <b>Hello World</b>")
0
votes

If you use androidx.* classes in your project, you should use HtmlCompat.fromHtml(text, flag).

Source of the method is:

@NonNull
    public static Spanned fromHtml(@NonNull String source, @FromHtmlFlags int flags) {
        if (Build.VERSION.SDK_INT >= 24) {
            return Html.fromHtml(source, flags);
        }
        //noinspection deprecation
        return Html.fromHtml(source);
    }

It is better to use HtmlCompat.fromHtml than Html.fromHtml as there is less code- only one line of code, and it's recommended way to use it.

0
votes

simply use enter image description here

checkBoxTextView.text =
        Html.fromHtml("<p><font color=#666666>I agree to</font><font color=#0173B7>  <b><u>Terms & Conditions</u></b></font><font color=#666666> and the <u></font><b><font color=#0173B7>Privacy Policy</font></u></b></font></p>")