简体   繁体   English

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

[英]Android HtmlCompat.toHtml(Spanned) returns improperly nested HTML tags

I have an Edittext (binding.text using view binding) that contains text styled with StyleSpans, ie bold and italics.我有一个 Edittext(使用视图绑定的 binding.text),其中包含使用 StyleSpan 设置样式的文本,即粗体和斜体。 To save the formatted text, I use HtmlCompat.toHtml(spannable) in Kotlin to convert it into HTML.为了保存格式化文本,我在 Kotlin 中使用 HtmlCompat.toHtml(spannable) 将其转换为 HTML。

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

However, the HTML returned is improperly nested if the text has bold and italics applied to it at the same time.但是,如果文本同时应用了粗体和斜体,则返回的 HTML 嵌套不正确。

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

As you can see, the tags applied are <b><i> </b></i> instead of <b><i> </i></b> .如您所见,应用的标签是<b><i> </b></i>而不是<b><i> </i></b>


When the text is not formatted, or either in bold or italics, then proper HTML is returned:如果文本没有格式化,或者是粗体或斜体,则返回正确的 HTML:

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

I suppose the function likes to put <b> and </b> first as opposed to <i> and </i> , but this causes weird results as shown.我想 function 喜欢把<b></b>放在第一位,而不是<i></i> ,但这会导致奇怪的结果,如图所示。 So the question: How do I get the function to return correctly formatted HTML?所以问题是:如何让 function 返回正确格式的 HTML?

You are right about the ordering, although the HTML should still display correctly in a browser.您的顺序是对的,尽管 HTML 仍应在浏览器中正确显示。 The offending code is in Html.java .违规代码在Html.java中。 Here is where the translations occur for <b></b> and <i></i> :以下是<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 is an array of spans. style是一个跨度数组。 This code scans forward through the spans to place the opening tags and backward to close the tags.此代码通过跨度向前扫描以放置开始标签,并向后扫描以关闭标签。 So, it looks like if your bold span and italic spans are different spans spanning the same text, then this code will produce properly nested tags.因此,如果您的粗体跨度和斜体跨度是跨越相同文本的不同跨度,那么此代码将生成正确嵌套的标签。

However, if one StyleSpan specifies both italic and bold, then the tag order will be as you report <b><i></b></i> .但是,如果一个StyleSpan指定了斜体和粗体,则标记顺序将与您报告的<b><i></b></i>相同。 The code that outputs the closing tags should place <i> before b .输出结束标签的代码应该将<i>放在b之前。 This looks like a bug and should be reported.这看起来像一个错误,应该报告。

I assume that you have one StyleSpan that is a bolded-italics span.我假设您有一个StyleSpan是粗斜体跨度。 The fix would be to split that span into two separate spans - a bold span and an italics span.解决方法是将该跨度拆分为两个单独的跨度 - 一个粗体跨度和一个斜体跨度。 The code should then work as expected.然后代码应该按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有Spanned强制转换的Html.toHtml(ClassCastException) <Android> - Html.toHtml with Spanned cast (ClassCastException) <Android> Android Html.toHtml(editText.getText())返回太多html标签 - Android Html.toHtml(editText.getText()) returns too many html tags Android HTML 类支持哪些 HTML 标签,我该如何使用 HtmlCompat? - Which HTML tags are supported by the Android HTML class and how do I use HtmlCompat? Android中的Spant和html格式 - Spanned and html format in Android Android HtmlCompat.fromHtml() 创建 Spanned 后如何停止 EditText 显示 javascript - How to stop EditText showing javascript after Android HtmlCompat.fromHtml() creates a Spanned Html.toHtml()未解析<small>标签</small> - Html.toHtml() is not parsing <small> tags Html.toHtml() 未解析 BackgroundColorSpan(Android Lollipop) - Html.toHtml() is not parsing BackgroundColorSpan (Android Lollipop) java Android Spanned Html.fromHtml(stringWithCDATA)仍将标签显示为文本 - java Android Spanned Html.fromHtml(stringWithCDATA) still shows tags as text Android 跨接 getSpanEnd() 返回错误值 - Android Spanned getSpanEnd() returns wrong value html在android中转换为粗体或斜体的字符串 - html converted bold or italic spanned string in android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM