Android N中已弃用Html.fromHtml函数

403

我正在使用Html.fromHtml将HTML呈现在TextView中。

Spanned result = Html.fromHtml(mNews.getTitle());
...
...
mNewsTitle.setText(result);

但是在Android N+中,Html.fromHtml已经被弃用。

我应该如何找到新的实现方式?

15个回答

806

更新: 如下面@Andy提到的 ,谷歌已经创建了HtmlCompat来替换下面的方法。在您的应用程序的build.gradle文件中添加此依赖项implementation 'androidx.core:core:1.0.1',确保使用最新版本的androidx.core:core

这使您可以使用:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

在Android N中,他们引入了一个新的Html.fromHtml方法。现在Html.fromHtml需要一个额外的参数,名为flags。这个标志可以让您更好地控制HTML的显示方式。

在Android N及以上版本中,您应该使用这种新方法。旧的方法已被弃用并可能会在未来的Android版本中删除。

您可以创建自己的Util方法,它将在较旧版本上使用旧方法,并在Android N及以上版本上使用更新的方法。如果您不添加版本检查,您的应用程序将在较低版本的Android上中断。您可以在您的Util类中使用此方法。

您可以在HtmlCompat文档中了解有关不同标志的更多信息。

@SuppressWarnings("deprecation")
public static Spanned fromHtml(String html){
    if(html == null){
        // return an empty spannable if the html is null
        return new SpannableString("");
    }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // FROM_HTML_MODE_LEGACY is the behaviour that was used for versions below android N
        // we are using this flag to give a consistent behaviour
        return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
    } else {
        return Html.fromHtml(html);
    }
}
你可以将 HTML.FROM_HTML_MODE_LEGACY 转换为一个附加参数,如果你想的话。这会让你更有控制权,选择使用哪个标志位。
你可以在Html类文档中了解更多有关不同标志位的信息。

2
零代表哪个标志? - ban-geoengineering
5
Html.FROM_HTML_MODE_LEGACYзҡ„дёӯж–Үзҝ»иҜ‘жҳҜвҖңHtml.FROM_HTML_MODE_LEGACYвҖқгҖӮ - ban-geoengineering
22
啊,等待类似于HtmlCompat的东西出现。 - vanomart
12
else下方添加//noinspection deprecation注释可以避免lint警告,这也很有用。 - Ted Hopp
1
这似乎也已经被弃用了,可以被替换为Html.FromHtml(htmlText, Android.Text.FromHtmlOptions.ModeLegacy); - flo1411
显示剩余5条评论

100

我收到了许多这样的警告,但我总是使用FROM_HTML_MODE_LEGACY,因此我创建了一个名为HtmlCompat的辅助类,其中包含以下内容:

   @SuppressWarnings("deprecation")
   public static Spanned fromHtml(String source) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY);
        } else {
            return Html.fromHtml(source);
        }
    }

2
与被接受的答案产生相同的效果,但+1是因为使用了SuppressWarnings注释。 - Stoycho Andreev
你能简单解释一下这个模式吗? - Ranjithkumar
你能提供所有的HtmlCompact吗?它在GitHub上看起来很酷。 - shareef
@shareef 我想帮你,但这只是一个单调无味的实用类,里面只有一个方法... - k2col
你也可以只使用HtmlCompat,避免检查Android版本。 - Ali Kazi

78

fromHtml()方法的标志比较。

<p style="color: blue;">This is a paragraph with a style</p>

<h4>Heading H4</h4>

<ul>
   <li style="color: yellow;">
      <font color=\'#FF8000\'>li orange element</font>
   </li>
   <li>li #2 element</li>
</ul>

<blockquote>This is a blockquote</blockquote>

Text after blockquote
Text before div

<div>This is a div</div>

Text after div

FROM_HTML FLAGS


请问您能否分享输入的HTML代码呢?这将有助于更好地理解转换过程。 - Kalpesh Patel
我看到样式属性没有被实现,有没有一种方法可以实现它们? - Christine

65

或者您可以使用androidx.core.text.HtmlCompat

HtmlCompat.fromHtml("<b>HTML</b>", HtmlCompat.FROM_HTML_MODE_LEGACY)

HtmlCompat 文档


你能在Android 5上使用这个吗? - CDrosos
1
@CDrosos 是的,它是支持库的一部分。 - Ondřej Z

30

如果您有幸在Kotlin上进行开发,只需创建一个扩展函数:

fun String.toSpanned(): Spanned {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
    } else {
        @Suppress("DEPRECATION")
        return Html.fromHtml(this)
    }
}

然后,将其应用到各处是如此美妙:

yourTextView.text = anyString.toSpanned()

5
去掉Spannedreturn可以节省输入。 - Minami

16
fromHtml

该方法已于API级别24中被弃用

您应该使用FROM_HTML_MODE_LEGACY

在块级元素之间用空行(即两个新行字符)进行分隔。这是N版本之前的传统行为。

代码

if (Build.VERSION.SDK_INT >= 24)
        {
            etOBJ.setText(Html.fromHtml("Intellij \n Amiyo",Html.FROM_HTML_MODE_LEGACY));

         }
 else
        {
           etOBJ.setText(Html.fromHtml("Intellij \n Amiyo"));
        }

对于 Kotlin

fun setTextHTML(html: String): Spanned
    {
        val result: Spanned = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY)
        } else {
            Html.fromHtml(html)
        }
        return result
    }

呼叫

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

你能简要地解释一下这个模式吗? - Ranjithkumar
如果您想让SDK处理版本检查,请使用以下代码:HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY) - Wajid

11

如果您正在使用Kotlin,我通过使用Kotlin扩展来实现这一点:

fun TextView.htmlText(text: String){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        setText(Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY))
    } else {
        setText(Html.fromHtml(text))
    }
}

然后像这样调用:

textView.htmlText(yourHtmlText)

你不需要添加else部分,fromHtml方法默认处理较低API设备的情况。 - Amir Dora.
你可以用以下代码替换if/else语句:HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY) - James

9

来自官方文档:

fromHtml(String)方法在API 24级别中已弃用。请使用fromHtml(String, int)代替。

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVE选项用于toHtml(Spanned, int): 将由'\n'分隔的连续文本行包装在<p>元素内。

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUAL选项用于toHtml(Spanned, int): 将由'\n'分隔的每一行文本分别包装在<p><li>元素内。

https://developer.android.com/reference/android/text/Html.html


6
对于 Kotlin 用户,我们可以使用 String.parseAsHtml() 扩展函数,该函数使用 HtmlCompat,后者具有兼容性检查。
这可从android核心Kotlin扩展中获得,即 androidx.core:core-ktx

5

仅仅是扩展@Rockney和@k2col的答案,改进后的代码可能如下:

@NonNull
public static Spanned fromHtml(@NonNull String html) {
    if (CompatUtils.isApiNonLowerThan(VERSION_CODES.N)) {
        return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
    } else {
        //noinspection deprecation
        return Html.fromHtml(html);
    }
}

CompatUtils.isApiNonLowerThan 的作用:

public static boolean isApiNonLowerThan(int versionCode) {
    return Build.VERSION.SDK_INT >= versionCode;
}

区别在于没有额外的局部变量,而且弃用只在 else 分支中。所以这不会抑制所有方法,而是单个分支。

当谷歌在将来的Android版本中决定甚至弃用 fromHtml(String source, int flags) 方法时,它可以帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接