2

我有一个 Edittext(使用视图绑定的 binding.text),其中包含使用 StyleSpan 设置样式的文本,即粗体和斜体。为了保存格式化的文本,我在 Kotlin 中使用 HtmlCompat.toHtml(spannable) 将其转换为 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:

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

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

4

1 回答 1

1

您对排序是正确的,尽管 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是一个跨度数组。此代码通过跨度向前扫描以放置开始标签,并向后扫描以关闭标签。因此,如果您的粗体跨度和斜体跨度是跨越相同文本的不同跨度,那么此代码将生成正确嵌套的标签。

但是,如果一个StyleSpan指定了斜体和粗体,那么标签顺序将与您报告的一样<b><i></b></i>。输出结束标签的代码应该<i>放在b. 这看起来像一个错误,应该报告。

我假设您有一个StyleSpan是粗斜体跨度。解决方法是将该跨度拆分为两个单独的跨度 - 一个粗体跨度和一个斜体跨度。然后代码应该按预期工作。

于 2021-05-05T12:18:12.360 回答