Android HtmlCompat.toHtml(Spanned)返回嵌套不正确的HTML标记



我有一个Edittext(使用视图绑定的binding.text(,它包含使用样式平移(即粗体和斜体(设置样式的文本。为了保存格式化的文本,我在Kotlin中使用HtmlCompat.toHtml(spanable(将其转换为HTML。

var htmlString = HtmlCompat.toHtml(SpannableString(binding.text.text), HtmlCompat.FROM_HTML_MODE_LEGACY)

但是,如果文本同时应用了粗体和斜体,则返回的HTML嵌套不正确。

  • 你好世界:输出<p dir="ltr><b><i>Hello world</b></i></p>

正如您所看到的,应用的标签是<b><i> </b></i>而不是<b><i> </i></b>


如果文本未格式化,或者为粗体或斜体,则返回正确的HTML:

  • Hello World:输出<p dir="ltr>Hello world</p>
  • Hello World:输出<p dir="ltr><b>Hello world</b></p>

我想函数喜欢把<b></b>放在第一位,而不是<i></i>,但这会导致奇怪的结果,如图所示。那么问题来了:如何让函数返回正确格式化的HTML?

您的排序是正确的,尽管HTML在浏览器中仍然应该正确显示。有问题的代码位于Html.java中。以下是<b></b><i></i>:的翻译位置

...
for (int j = 0; j < style.length; j++) {    
...
if (style[j] instanceof StyleSpan) {
int s = ((StyleSpan) style[j]).getStyle();

if ((s & Typeface.BOLD) != 0) {
out.append("<b>");
}
if ((s & Typeface.ITALIC) != 0) {
out.append("<i>");
}
}
...
for (int j = style.length - 1; j >= 0; j--) {
,,,
if (style[j] instanceof StyleSpan) {
int s = ((StyleSpan) style[j]).getStyle();

if ((s & Typeface.BOLD) != 0) {
out.append("</b>");
}
if ((s & Typeface.ITALIC) != 0) {
out.append("</i>");
}
}

style是跨度的阵列。此代码向前扫描跨度以放置打开的标记,向后扫描以关闭标记。因此,如果粗体和斜体跨度是跨越同一文本的不同跨度,那么这段代码将生成正确的嵌套标记。

但是,如果一个样式平移同时指定了斜体和粗体,则标记顺序将与报告<b><i></b></i>时相同。输出结束标记的代码应该将<i>放在b之前。这看起来像是一个错误,应该报告。

我假设您有一个样式span,它是粗体斜体span。修复方法是将该跨度拆分为两个单独的跨度——一个粗体跨度和一个斜体跨度。然后,代码应该按预期工作。

最新更新