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?
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?
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)
}
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.
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"/>
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.
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).
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
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.
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
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.
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:
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);
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);
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));
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()));
}
}
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
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;
}
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.
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.