882

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?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
UMAR-MOBITSOLUTIONS
  • 77,236
  • 95
  • 209
  • 278
  • 8
    Do you want to display the tags or omit them? – DerMike Jan 22 '10 at 09:18
  • 1
    check out this link for working example http://javatechig.com/2013/04/07/how-to-display-html-in-android-view/ – Nilanchala Apr 07 '13 at 20:28
  • 1
    If you are looking for deprecated's solution, it just right here http://stackoverflow.com/questions/37904739/html-fromhtml-deprecated-in-android-n – crgarridos Aug 01 '16 at 09:27
  • textview.setText(Html.fromHtml("your HTML")); is best method to show only HTML tags. also there is a method to play JS. – CleanCoder Jul 03 '20 at 14:42
  • Android does not support all the HTML tags. Check this https://arkapp.medium.com/android-set-html-in-text-view-b912e1a96b21 to understand better how to use in text view. – abdul rehman Feb 20 '21 at 07:22

29 Answers29

1569

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)
}
Boken
  • 4,825
  • 10
  • 32
  • 42
David Hedlund
  • 128,221
  • 31
  • 203
  • 222
  • when i put these lines gap occurs between h2 and p even i have removed br but still there is a gap...how to resolve it?? – UMAR-MOBITSOLUTIONS Jan 22 '10 at 10:12
  • 9
    `h2` by definition creates a lot of margin around itself. and `p` also comes with some margin. if you don't want the gap, you might want to consider using other html elements. – David Hedlund Jan 22 '10 at 10:58
  • how can I set html text within style attribute to textview control? It probably not work. – Nguyen Minh Binh Jul 15 '11 at 04:06
  • 2
    Can I put tags in XML strings? – Kostadin Jan 16 '12 at 08:09
  • 11
    Kostadin, you can put tags in XML, you just need to wrap them in CDATA brackets. – Gerard Apr 29 '12 at 12:24
  • 2
    Can't we put
    like over here?
    – Ketan Bhavsar May 23 '13 at 10:39
  • 3
    For those who want it to work with the ol/ul/li tags, check out this solution: http://stackoverflow.com/a/3150456/1369016 – Bitcoin Cash - ADA enthusiast Aug 26 '13 at 00:38
  • 14
    That should be `android.text.Html.fromHtml`. I know most IDEs will fix it for you but for readability it is nicer to know the package names. – Martin Oct 22 '13 at 12:22
  • 2
    A list of tags supported by this method can be found [here](http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html) – Mahm00d May 27 '14 at 04:55
  • 14
    @Martin I wouldn't say *for readability* but rather *for exhaustivity*. IMO fully qualified names used directly in code like this are less readable than short names. But I agree with you on the fact that an answer like this should provide the package (on a side note), which the point of the link here ;) – Joffrey Jun 19 '14 at 09:42
  • This actually fixed a problem with rendering RSS feeds that contained HTML data.... If you get strange character encoding errors like the "diamond", it's probably caused by HTML within with RSS content which can be resolved with this solution +100 – angryITguy Feb 11 '15 at 04:34
  • any idea, how to display div content value in textview, here is the my problem: http://stackoverflow.com/questions/29512453/how-to-display-div-html-content-in-android-on-textview – Bixms Apr 08 '15 at 10:46
  • This html doesn't display formatted:

    Suspected jihadists kill three at U.N. base in north Mali

    By Tiemoko Diallo

    BAMAKO (Reuters) - The United Nations said unknown attackers fired rockets at a U.N. peacekeeping base in Kidal in northern Mali on Saturday, killing three people inside, in the latest sign that the West African country's Islamist insurgency is intensifying.

    – Johann Nov 28 '15 at 15:27
  • Why Html.fromHtml(htmlText) returns commented texts if it exists? – nAkhmedov Mar 28 '16 at 08:14
  • It doesn't do alignment either. So pretty much useless, like most Android apis. – RunLoop May 07 '16 at 07:30
  • 1
    @Guy: Nop. It doesn't work for
      and
    • . Not just them, there are few other tags as well which does not work with this. Check this out: http://stackoverflow.com/a/3150456/1987045
    – rahulrvp Sep 28 '16 at 12:49
  • 3
    This method was deprecated in API level 24 – emir Oct 14 '16 at 15:19
  • Deprecated function. – beetree Dec 10 '16 at 20:05
  • 1
    For Deprecated funcion: http://stackoverflow.com/questions/37904739/html-fromhtml-deprecated-in-android-n – Marcus Becker Dec 27 '16 at 16:48
  • Small update: add annotation: @RequiresApi(api = Build.VERSION_CODES.N), for version compatibility – Kshitij Jhangra Oct 10 '18 at 04:16
  • How can i do this if i get string from json by volley? – Ali Khaki Nov 05 '18 at 09:05
  • java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference – Web.11 Jan 28 '21 at 15:28
  • Yeah this works fine but hyperlink showing in white color . – Surajkaran Meghwanshi Jan 05 '23 at 06:02
89

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));
 }
Shohan Ahmed Sijan
  • 4,391
  • 1
  • 33
  • 39
74

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.

Community
  • 1
  • 1
Felipe
  • 16,649
  • 11
  • 68
  • 92
46

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"/>
johannchopin
  • 13,720
  • 10
  • 55
  • 101
user1299412
  • 389
  • 6
  • 15
39

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.

Community
  • 1
  • 1
Phileo99
  • 5,581
  • 2
  • 46
  • 54
30

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

Julian A.
  • 10,928
  • 16
  • 67
  • 107
Shashanth
  • 4,995
  • 7
  • 41
  • 51
27

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);
JJD
  • 50,076
  • 60
  • 203
  • 339
Rajiv Manivannan
  • 504
  • 7
  • 15
14
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());
Pedro
  • 11
  • 2
  • 5
13

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.

prom85
  • 16,896
  • 17
  • 122
  • 242
  • 3
    While this is a very useful way to get around the restricted set of html tags, supported by TextView, it has the disadvantage that it **does not work well** with `layout_height="wrap_content"`. You will have to set an explicit height or match_parent instead. – Ridcully Oct 09 '16 at 05:16
  • 5
    webview is very slow – Jackky777 Feb 26 '17 at 08:42
12

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

Flexo
  • 87,323
  • 22
  • 191
  • 272
Rajendhiran Easu
  • 273
  • 4
  • 14
  • Thanks, this did it for me- using API 23. – XMAN Mar 19 '17 at 19:24
  • thanks, u saved my day :) Just a small addition : We need to add this check to above code: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // for 24 api and more textView.setText(Html.fromHtml(welcomStr, Html.FROM_HTML_OPTION_USE_CSS_COLORS)); } else { // or for older api textView.setText(Html.fromHtml(welcomStr)); } . The value for 2nd parameter flag for API>=24, can be anything as per requirement. – AndroidGuy Apr 13 '17 at 05:40
10

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.

Teo Inke
  • 5,928
  • 4
  • 38
  • 37
10

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)
}
Roman
  • 2,464
  • 2
  • 17
  • 21
6

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

  • I am getting following error : Error:(80, 13) Failed to resolve: com.osbcp.cssparser:cssparser:1.5 How do I resolve this ? – Araju Aug 18 '17 at 09:45
6

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);
Prags
  • 2,457
  • 2
  • 21
  • 38
Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
  • @MartijnPieters The previously closed answer was a duplicate of an answer to [this question in relation to the deprecation of a framework method](http://stackoverflow.com/q/37904739/154306). I've expanded on the reason using a compatibility library would be a better approach. I don't think it's reasonable to flag either question as duplicates of each other as they are clearly different. – Paul Lammertsma Mar 15 '17 at 14:00
5

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.

damgad
  • 1,446
  • 9
  • 24
java dev
  • 1,044
  • 1
  • 11
  • 17
5

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.

androidEnthusiast
  • 1,140
  • 1
  • 12
  • 21
5

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>")
Sandeep Pareek
  • 1,636
  • 19
  • 21
4

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);
Shubham AgaRwal
  • 4,355
  • 8
  • 41
  • 62
4
String value = html value ....
mTextView.setText(Html.fromHtml(value),TextView.BufferType.SPANNABLE)
SeniorJD
  • 6,946
  • 4
  • 36
  • 53
4

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));
Shailendra Madda
  • 20,649
  • 15
  • 100
  • 138
2

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()));
    }
}
Salvioner
  • 303
  • 5
  • 16
Vinayak
  • 6,056
  • 1
  • 32
  • 30
2

Simply use:

String variable="StackOverflow";
textView.setText(Html.fromHtml("<b>Hello : </b>"+ variable));
Sumit Shukla
  • 4,116
  • 5
  • 38
  • 57
2

People have suggested subclass for TextView, WebView and all sorts of solutions. I wonder why nobody mentioned a simple binding adapter.

@BindingAdapter(value = ["htmlText"])
fun TextView.setHtmlText(string: String?) {
    text = HtmlCompat.fromHtml(string?:"", HtmlCompat.FROM_HTML_MODE_COMPACT)
}

So your TextView xml will look like

<TextView
   ...
   htmlText="<p>Your <b>HTML</b> text</p>"
   ... />
shahrukhamd
  • 259
  • 6
  • 6
1
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

Isaac Sekamatte
  • 5,500
  • 1
  • 34
  • 40
1

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;
}
Somesh Kumar
  • 8,088
  • 4
  • 33
  • 49
1

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>")
seyfullah.bilgin
  • 1,421
  • 14
  • 16
0

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.

AXE
  • 8,335
  • 6
  • 25
  • 32
0

Using BindingAdapter:

@BindingAdapter("renderHtml")
fun bindRenderHtml(view: TextView, description: String?) {
if (description != null) {
    view.text = HtmlCompat.fromHtml(description, FROM_HTML_MODE_COMPACT)
    view.movementMethod = LinkMovementMethod.getInstance()
} else {
    view.text = ""
}

}

usage:

  <TextView
        android:id="@+id/content_text_view"
        app:renderHtml="@{show.description}"
        ...
Dan Alboteanu
  • 9,404
  • 1
  • 52
  • 40
-1

You can build valid HTML for Android TextView using the HtmlDsl library on Github: https://github.com/jaredrummler/HtmlDsl.

The library provides syntactic sugar to make the code more understandable and less error-prone by only supporting elements and attributes that are rendered by Android.

Example creating some HTML:

textView.setHtml {
    h3("Android Versions:")
    ul {
        li {
            a(href = "https://developer.android.com/about/versions/12/get") {
                +"Android 12 Beta"
            }
        }
        li("Android 11")
        li("Android 10")
        li("Pie")
        li("Oreo")
        li("Nougat")
        li("Marshmallow")
        li("Lollipop")
        // ...
    }

    small {
        sub {
            +"by "
            a {
                href = "https://github.com/jaredrummler"
                text = "Jared Rummler"
            }
        }
    }
}

Supported HTML elements for Android TextView:

<a href="...">
<b>
<big>
<blockquote>
<br>
<cite>
<dfn>
<div align="...">
<em>
<font color="..." face="...">
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<i>
<img src="...">
<p>
<small>
<strike>
<strong>
<sub>
<sup>
<tt>
<u>
<ul>
<li>
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148