设置TextView文本从html格式的字符串资源在XML

我在strings.xml中有一些固定的字符串,比如:

<resources>
<string name="somestring">
<B>Title</B><BR/>
Content
</string>
</resources>

在我的布局中,我有一个TextView,我想用html格式的字符串填充。

<TextView android:id="@+id/formattedtext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/htmlstring"/>

如果我这样做,formattedtext的内容只是除去任何html标记的somestring的内容,因此没有格式化。

我知道可以用编程方式设置格式化文本

.setText(Html.fromHtml(somestring));

因为我在程序的其他部分使用了这个,在那里它是正常工作的。

要调用这个函数,我需要一个Activity,但目前我的布局只是一个简单的或多或少静态的纯XML视图,我宁愿让它保持这种状态,以节省创建Activity来设置一些文本的开销。

我是不是忽略了一些显而易见的东西?难道根本不可能吗?欢迎任何帮助或解决办法!

编辑:刚刚尝试了一些东西,似乎HTML格式在xml有一些限制:

  • 标签必须小写

  • 这里提到的一些标签 是无效的,例如<br/>(可以使用\n代替)

227779 次浏览

转义你的HTML标签…

<resources>
<string name="somestring">
&lt;B&gt;Title&lt;/B&gt;&lt;BR/&gt;
Content
</string>
</resources>

为了防止有人发现这个问题,还有一个更好的替代方案没有被记录下来(我在搜索了几个小时后偶然发现了它,最终在Android SDK本身的漏洞列表中找到了它)。你<强> < / >强能包含原始HTML在strings.xml,只要你包装它

<![CDATA[ ...raw html... ]]>

边界情况:

    像撇号('),双引号(")和&号(&)这样的字符只需要转义,如果你想让它们作为自己出现在渲染的文本中,但它们可以合理地解释为HTML。
    • '"可以表示为__abc2和\",或者&apos;&quot;
    • <> 总是需要转义为&lt;&gt;,如果你想让它们在文本中呈现为'<'和'>'。
    • & & (&)稍微复杂一些。
      • &后跟空格呈现为&。
      • &号后面跟着一个或多个字符,这些字符不能形成有效的HTML实体代码,呈现为&号后面跟着这些字符。所以…&qqq;呈现为&qqq;,而&lt;1呈现为<1

例子:

<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 &lt; 1, & 10 &gt; 1<p>
]]>
</string>

然后,在你的代码中:

TextView foo = (TextView)findViewById(R.id.foo);
foo.setText(Html.fromHtml(getString(R.string.nice_html), FROM_HTML_MODE_LEGACY));

恕我直言,这是几个数量级更好的工作:-)


2021年8月更新:我最初的答案使用Html.fromHtml(String),这在API 24中已弃用。建议将其替换为fromHtml (String、int)形式。

FROM_HTML_MODE_LEGACY可能工作…但是对于您想要做的事情,其他标志之一可能是更好的选择。

最后一点,如果你更喜欢使用减价语法而不是HTML来渲染适合在TextView中使用的Android span文本,现在有多个第三方库来简化它,包括https://noties.io/Markwon

因为上面的答案暗示了一些错误(或至少太复杂),我觉得这个应该更新,尽管这个问题相当老:

当在Android中使用String资源时,你只需要从Java代码中调用getString(...)或在布局XML中使用android:text="@string/..."

即使你想在你的字符串中使用HTML标记,你也不需要做很多改变:

在String资源中唯一需要转义的字符是:

  • 双引号:"变成\"
  • 单引号:'变成\'
  • &号:&变成&#38;&amp;

这意味着你可以添加你的没有转义的HTML标记标签:

<string name="my_string"><b>Hello World!</b> This is an example.</string>

但是,可以肯定的是,你应该只使用文档中列出的<b><i><u>

如果你想使用你的HTML字符串从XML,只要继续使用android:text="@string/...",它会工作的很好。

唯一的区别是,如果你想使用你的HTML字符串来自Java代码,你现在必须使用getText(...)而不是getString(...),因为前者保留了风格,而后者只会剥离它。

就这么简单。没有CDATA,没有Html.fromHtml(...)

如果在HTML标记中使用做了编码特殊字符,则只需要Html.fromHtml(...)。然后与getString(...)一起使用它。如果你想将String传递给String.format(...),这可能是必要的。

这些都是在文档中描述的。

编辑:

带有未转义HTML的getText(...)(如我所提议的)或CDATA节和Html.fromHtml(...)之间没有区别。

对比如下图所示:

enter image description here

我有另一种情况,当我没有机会把CDATA放入xml,因为我从服务器接收字符串HTML。

以下是我从服务器上得到的信息:

<p>The quick brown&nbsp;<br />
fox jumps&nbsp;<br />
over the lazy dog<br />
</p>

它看起来更复杂,但解决方法要简单得多。

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());


}
希望这对你有帮助!< br > 灵< / p >

Android没有指定资源字符串的类型(例如text/plain或text/html)。但是,有一种变通方法允许开发人员在XML文件中指定这一点。

  1. 定义一个自定义属性,指定android:text属性为html。
  2. 使用子类化的TextView。

一旦你定义了这些,你就可以在xml文件中使用HTML来表达自己,而不必再次调用setText(HTML . fromhtml(…))。我很惊讶这个方法不是API的一部分。

这个解决方案的工作程度,Android工作室模拟器将显示文本作为渲染的HTML。

enter image description here

res/values/strings.xml (HTML格式的字符串资源)

<resources>
<string name="app_name">TextViewEx</string>
<string name="string_with_html"><![CDATA[
<em>Hello</em> <strong>World</strong>!
]]></string>
</resources>

xml(只包含相关部分)

声明自定义属性名称空间,并添加android_ex:isHtml属性。也可以使用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(为子类定义自定义属性)

 <resources>
<declare-styleable name="TextViewEx">
<attr name="isHtml" format="boolean"/>
<attr name="android:text" />
</declare-styleable>
</resources>

java (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();
}
}
}

最新更新:

Html.fromHtml(string);// Android N版本后已弃用。

以下代码支持android N及以上版本…

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

如果你想显示html scrip在android应用程序像TextView

请遵循以下代码

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