从 XML 中的 html 格式的字符串资源设置 TextView 文本
Posted
技术标签:
【中文标题】从 XML 中的 html 格式的字符串资源设置 TextView 文本【英文标题】:Set TextView text from html-formatted string resource in XML 【发布时间】:2011-03-15 04:32:56 【问题描述】:我的strings.xml
中有一些固定字符串,例如:
<resources>
<string name="somestring">
<B>Title</B><BR/>
Content
</string>
</resources>
在我的布局中,我有一个 TextView
,我想用 html 格式的字符串填充它。
<TextView android:id="@+id/formattedtext"
android:layout_
android:layout_
android:text="@string/htmlstring"/>
如果我这样做,formattedtext
的内容就是 somestring
的内容,去掉了任何 html 标签,因此没有格式化。
我知道可以使用
以编程方式设置格式化文本.setText(Html.fromHtml(somestring));
因为我在程序的其他部分使用它,它按预期工作。
要调用这个函数,我需要一个Activity
,但目前我的布局只是一个简单的或多或少是纯 XML 的静态视图,我宁愿保持这种状态,以节省我的开销创建一个Activity
只是为了设置一些文本。
我是否忽略了一些明显的东西?根本不可能吗?欢迎任何帮助或解决方法!
编辑:刚刚尝试了一些东西,似乎 xml 中的 HTML 格式有一些限制:
标签必须小写
here 中提到的某些标签不起作用,例如<br/>
(可以改用\n
)
【问题讨论】:
现在我知道很久了,但是我能够使用 而不是 \n 使用 html 作为 TextView 的新行。 这可以仅从 xml 工作吗?我对答案有一点赏金。在这一点上,我已经围绕它进行了编码,我认为不作为事实答案。 我觉得有趣的是没有人真正回答这个问题。 OP 声明他知道如何使用 fromHtml(),但想直接在布局文件中进行(尽管原因并不好......如果你正在绘制,你总是有一个活动/上下文可用屏幕)。也没有一个答案深入到锚标签的影响。 【参考方案1】:以防万一有人发现这一点,有一个更好的替代方案没有记录(我在搜索了几个小时后绊倒了它,最后在 Android SDK 本身的错误列表中找到了它)。您可以在 strings.xml 中包含原始 HTML,只要您将其包装在
中<![CDATA[ ...raw html... ]]>
边缘案例:
如果您希望撇号 (')、双引号 (") 和 & 号 (&) 等字符出现在呈现的文本 AS 本身中,则只需要对其进行转义,但它们可以被合理地解释为 HTML。'
和"
可以表示为\'
和\"
,或者&apos;
和&quot;
。
&lt;
和 &gt;
总是 需要转义为 &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 < 1, & 10 > 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 可能会起作用...但其他标志之一可能是您想要做的更好的选择。
最后一点,如果您希望使用 Markdown 语法而不是 HTML 来呈现适合在 TextView 中使用的 Android Spanned 文本,现在有多个第三方库可以轻松实现,包括 @ 987654322@.
【讨论】:
只是补充一下,您还可以在 CDATA 块内使用反斜杠转义撇号/单引号,这样您就可以使用 can\'t 之类的东西,而不是无限地-丑的不能 这还能用吗?我刚试了一下,它确实显示了和
。 @PeriHartman 你也做了Html.fromHtml(getString(R.string.nice_html))
位吗? :)
TextView foo = (TextView)findViewById(R.id.foo); foo.setText(Html.fromHtml(getString(R.string.nice_html)));需要去吗?
有没有办法避免“Html.fromHtml”?【参考方案2】:
由于这里的最佳答案暗示了一些错误(或至少太复杂),我觉得这应该更新,尽管这个问题已经很老了:
在 Android 中使用字符串资源时,您只需从 Java 代码中调用 getString(...)
或在布局 XML 中使用 android:text="@string/..."
。
即使你想在你的字符串中使用 HTML 标记,你也不必做很多改变:
您需要在字符串资源中转义的唯一字符是:
双引号:"
变成\"
单引号:'
变成\'
& 符号:&amp;
变为 &#38;
或 &amp;
这意味着您可以添加 HTML 标记而不转义标签:
<string name="my_string"><b>Hello World!</b> This is an example.</string>
但是,可以肯定的是,您应该只使用文档中列出的 <b>
、<i>
和 <u>
。
如果您想使用 来自 XML 的 HTML 字符串,请继续使用 android:text="@string/..."
,它将正常工作。
唯一的区别是,如果你想使用 来自 Java 代码的 HTML 字符串,你现在必须使用 getText(...)
而不是 getString(...)
,因为前者保留了样式和后者只会将其剥离。
就这么简单。没有 CDATA,没有 Html.fromHtml(...)
。
如果您确实在 HTML 标记中编码您的特殊字符,您将只需要Html.fromHtml(...)
。然后将其与getString(...)
一起使用。如果您想将字符串传递给String.format(...)
,这可能是必要的。
in the docs 也描述了这一切。
编辑:
getText(...)
与未转义的 HTML(正如我建议的那样)或 CDATA
部分和 Html.fromHtml(...)
之间没有区别。
请参见下图进行比较:
【讨论】:
我的正在剥离它。我正在使用以下代码:getResources().getText(R.string.codename)
为了更好地提供帮助,我需要查看 Java/XML 摘录。但正如我所写:你只能确定你是否使用<b>
、<i>
、<u>
。并不总是支持其他标签。
您的答案有效且简单。只需将带有所需 html 标记的字符串放入 strings.xml 中,然后从您的布局 xml 文件中引用它。我使用了 标签。
Yours 是另一种解决方案,而不是另一种解决方案,因为它不支持所有标签,就像另一个一样。当另一个非常简单时,我看不到这个解决方案有任何优势。
我在使用“CDATA”时遇到了问题,例如: 有 22 个字母,html 部分有 10 个。因此,如果您使用 HTML.fromhtml(getstring(...)) 您的文本将正确显示,但文本的内容需要 22 个字母空格。我在 listview 中使用并看到杂草空间。所以 gettext() 更好。【参考方案3】:
转义 HTML 标签 ...
<resources>
<string name="somestring">
<B>Title</B><BR/>
Content
</string>
</resources>
【讨论】:
这就是文档所说的:developer.android.com/intl/zh-TW/guide/topics/resources/…,但这足以让TextView
显示 HTML 吗?
这个我已经测试过了,如果你从java源代码中使用它就可以了。但是,如果您直接从布局 XML 关联文本,则标签会显示在文本视图中(例如 Title ...)
要在视图中显示文本,请使用类 [developer.android.com/reference/android/text/Html.html],特别是 fromHTML()
。
@ZoltanF 是对的,在 HTML 布局中使用 android:text="" 将显示字符串中的标签。
如果您想直接从 XML 使用 HTML 字符串,您可以不在字符串中编码 HTML 特殊字符。但是,如果您想通过Html.fromHTML()
使用代码中的字符串,您必须 对特殊字符进行编码。奇怪!【参考方案4】:
Android 没有说明资源字符串类型的规范(例如 text/plain 或 text/html)。但是,有一种解决方法允许开发人员在 XML 文件中指定它。
-
定义一个自定义属性以指定 android:text 属性为 html。
使用子类 TextView。
一旦定义了这些,您就可以在 xml 文件中使用 HTML 来表达自己,而无需再次调用 setText(Html.fromHtml(...))。我很惊讶这种方法不是 API 的一部分。
此解决方案的工作原理是 Android Studio 模拟器将文本显示为呈现的 HTML。
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>
layout.xml(仅相关部分)
声明自定义属性命名空间,并添加 android_ex:isHtml 属性。也可以使用 TextView 的子类。
<RelativeLayout
...
xmlns:android_ex="http://schemas.android.com/apk/res-auto"
...>
<tv.twelvetone.samples.textviewex.TextViewEx
android:layout_
android:layout_
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>
TextViewEx.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 格式的字符串,而不是在每个地方调用 HTML.fromHtml。应用程序本身将有两个视图,一个用于普通视图,一个用于 HTML。【参考方案5】:最新更新:
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));
【讨论】:
【参考方案6】: 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);
【讨论】:
【参考方案7】:当我从服务器接收到字符串 HTML 时,我没有机会将 CDATA 放入 xml 中。
这是我从服务器得到的:
<p>The quick brown <br />
fox jumps <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());
希望对您有所帮助! 灵儿
【讨论】:
getHTMLContentFromAServer() 函数的实现在哪里【参考方案8】:如果您想在 Android 应用中显示 html 脚本,例如 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))
【讨论】:
以上是关于从 XML 中的 html 格式的字符串资源设置 TextView 文本的主要内容,如果未能解决你的问题,请参考以下文章
android listview中的文字大小能在string.xml里设置吗