Set TextView text from html-formatted string resource in XML
I have some fixed strings inside my strings.xml
, something like:
<resources>
<string name="somestring">
<B>Title</B><BR/>
Content
</string>
</resources>
and in my layout I've got a TextView
which I'd like to fill with the html-formatted string.
<TextView android:id="@+id/formattedtext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/htmlstring"/>
if I do this, the content of formattedtext
is just the content of somestring
stripped of any html tags开发者_StackOverflow社区 and thus unformatted.
I know that it is possible to set the formatted text programmatically with
.setText(Html.fromHtml(somestring));
because I use this in other parts of my program where it is working as expected.
To call this function I need an Activity
, but at the moment my layout is just a simple more or less static view in plain XML and I'd prefer to leave it that way, to save me from the overhead of creating an Activity
just to set some text.
Am I overlooking something obvious? Is it not possible at all? Any help or workarounds welcome!
Edit: Just tried some things and it seems that HTML formatting in xml has some restraints:
tags must be written lowercase
some tags which are mentioned here do not work, e.g.
<br/>
(it's possible to use\n
instead)
Just in case anybody finds this, there's a nicer alternative that's not documented (I tripped over it after searching for hours, and finally found it in the bug list for the Android SDK itself). You CAN include raw HTML in strings.xml, as long as you wrap it in
<![CDATA[ ...raw html... ]]>
Edge Cases:
- Characters like apostrophe ('), double-quote ("), and ampersand (&) only need to be escaped if you want them to appear in the rendered text AS themselves, but they COULD be plausibly interpreted as HTML.
'
and"
can be represented as\'
and\"
, or'
and"
.<
and>
always need to be escaped as<
and>
if you literally want them to render as '<' and '>' in the text.- Ampersand (&) is a little more complicated.
- Ampersand followed by whitespace renders as ampersand.
- Ampersand followed by one or more characters that don't form a valid HTML entity code render as Ampersand followed by those characters. So...
&qqq;
renders as&qqq;
, but<1
renders as<1
.
Example:
<string name="nice_html">
<![CDATA[
<p>This is a html-formatted \"string\" with <b>bold</b> and <i>italic</i> text</p>
<p>This is another paragraph from the same \'string\'.</p>
<p>To be clear, 0 < 1, & 10 > 1<p>
]]>
</string>
Then, in your code:
TextView foo = (TextView)findViewById(R.id.foo);
foo.setText(Html.fromHtml(getString(R.string.nice_html), FROM_HTML_MODE_LEGACY));
IMHO, this is several orders of magnitude nicer to work with :-)
August 2021 update: My original answer used Html.fromHtml(String), which was deprecated in API 24. The alternative fromHtml(String,int) form is suggested as its replacement.
FROM_HTML_MODE_LEGACY is likely to work... but one of the other flags might be a better choice for what you want to do.
On a final note, if you'd prefer to render Android Spanned text suitable for use in a TextView using Markdown syntax instead of HTML, there are now multiple thirdparty libraries to make it easy including https://noties.io/Markwon.
As the top answer here is suggesting something wrong (or at least too complicated), I feel this should be updated, although the question is quite old:
When using String resources in Android, you just have to call getString(...)
from Java code or use android:text="@string/..."
in your layout XML.
Even if you want to use HTML markup in your Strings, you don't have to change a lot:
The only characters that you need to escape in your String resources are:
- double quotation mark:
"
becomes\"
- single quotation mark:
'
becomes\'
- ampersand:
&
becomes&
or&
That means you can add your HTML markup without escaping the tags:
<string name="my_string"><b>Hello World!</b> This is an example.</string>
However, to be sure, you should only use <b>
, <i>
and <u>
as they are listed in the documentation.
If you want to use your HTML strings from XML, just keep on using android:text="@string/..."
, it will work fine.
The only difference is that, if you want to use your HTML strings from Java code, you have to use getText(...)
instead of getString(...)
now, as the former keeps the style and the latter will just strip it off.
It's as easy as that. No CDATA, no Html.fromHtml(...)
.
You will only need Html.fromHtml(...)
if you did encode your special characters in HTML markup. Use it with getString(...)
then. This can be necessary if you want to pass the String to String.format(...)
.
This is all described in the docs as well.
Edit:
There is no difference between getText(...)
with unescaped HTML (as I've proposed) or CDATA
sections and Html.fromHtml(...)
.
See the following graphic for a comparison:
Escape your HTML tags ...
<resources>
<string name="somestring">
<B>Title</B><BR/>
Content
</string>
</resources>
Android does not have a specification to indicate the type of resource string (e.g. text/plain or text/html). There is a workaround, however, that will allow the developer to specify this within the XML file.
- Define a custom attribute to specify that the android:text attribute is html.
- Use a subclassed TextView.
Once you define these, you can express yourself with HTML in xml files without ever having to call setText(Html.fromHtml(...)) again. I'm rather surprised that this approach is not part of the API.
This solution works to the degree that the Android studio simulator will display the text as rendered HTML.
res/values/strings.xml (the string resource as HTML)
<resources>
<string name="app_name">TextViewEx</string>
<string name="string_with_html"><![CDATA[
<em>Hello</em> <strong>World</strong>!
]]></string>
</resources>
layout.xml (only the relevant parts)
Declare the custom attribute namespace, and add the android_ex:isHtml attribute. Also use the subclass of TextView.
<RelativeLayout
...
xmlns:android_ex="http://schemas.android.com/apk/res-auto"
...>
<tv.twelvetone.samples.textviewex.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/string_with_html"
android_ex:isHtml="true"
/>
</RelativeLayout>
res/values/attrs.xml (define the custom attributes for the subclass)
<resources>
<declare-styleable name="TextViewEx">
<attr name="isHtml" format="boolean"/>
<attr name="android:text" />
</declare-styleable>
</resources>
TextViewEx.java (the subclass of TextView)
package tv.twelvetone.samples.textviewex;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.Nullable;
import android.text.Html;
import android.util.AttributeSet;
import android.widget.TextView;
public TextViewEx(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextViewEx, 0, 0);
try {
boolean isHtml = a.getBoolean(R.styleable.TextViewEx_isHtml, false);
if (isHtml) {
String text = a.getString(R.styleable.TextViewEx_android_text);
if (text != null) {
setText(Html.fromHtml(text));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
a.recycle();
}
}
}
Latest update:
Html.fromHtml(string);
//deprecated after Android N versions..
Following code give support to android N and above versions...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
textView.setText(Html.fromHtml(yourHtmlString,Html.FROM_HTML_MODE_LEGACY));
}
else
{
textView.setText(Html.fromHtml(yourHtmlString));
}
String termsOfCondition="<font color=#cc0029>Terms of Use </font>";
String commma="<font color=#000000>, </font>";
String privacyPolicy="<font color=#cc0029>Privacy Policy </font>";
Spanned text=Html.fromHtml("I am of legal age and I have read, understood, agreed and accepted the "+termsOfCondition+commma+privacyPolicy);
secondCheckBox.setText(text);
I have another case when I have no chance to put CDATA into the xml as I receive the string HTML from a server.
Here is what I get from a server:
<p>The quick brown <br />
fox jumps <br />
over the lazy dog<br />
</p>
It seems to be more complicated but the solution is much simpler.
private TextView textView;
protected void onCreate(Bundle savedInstanceState) {
.....
textView = (TextView) findViewById(R.id.text); //need to define in your layout
String htmlFromServer = getHTMLContentFromAServer();
textView.setText(Html.fromHtml(htmlFromServer).toString());
}
Hope it helps!
Linh
If you want to show html scrip in android app Like TextView
Please follow this code
Kotlin
var stringvalue = "Your Sting"
yourTextVew.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(stringvalue, Html.FROM_HTML_MODE_COMPACT)
} else {
Html.fromHtml(stringvalue)
}
Java
String stringvalue = "Your String";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
yourTextVew.setText(Html.fromHtml(stringvalue, Html.FROM_HTML_MODE_COMPACT))
} else {
yourTextVew.setText( Html.fromHtml(stringvalue))
}
精彩评论