【问题标题】:Html.fromHtml deprecated in Android NAndroid N 中不推荐使用 Html.fromHtml
【发布时间】:2016-10-20 15:49:37
【问题描述】:

我正在使用Html.fromHtmlTextView 中查看html。

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

Html.fromHtml 现在在 Android N+ 中已弃用

什么/如何找到执行此操作的新方法?

【问题讨论】:

    标签: android deprecated android-7.0-nougat


    【解决方案1】:

    更新: 正如@Andy mentioned below 谷歌已经创建了HtmlCompat 可以用来代替下面的方法。添加这个依赖implementation 'androidx.core:core:1.0.1 到您的应用程序的 build.gradle 文件。确保您使用最新版本的androidx.core:core

    这允许您使用:

    HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);
    

    您可以在HtmlCompat-documentation 上阅读有关不同标志的更多信息

    原答案: 在 Android N 中,他们引入了一个新的Html.fromHtml 方法。 Html.fromHtml 现在需要一个名为 flags 的附加参数。此标志使您可以更好地控制 HTML 的显示方式。

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

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

    @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 class documentation

    【讨论】:

    • 零代表哪个标志?
    • Html.FROM_HTML_MODE_LEGACY
    • 啊,等待HtmlCompat之类的出现
    • else 下方添加//noinspection deprecation 评论也很有用,以避免出现lint 警告。
    • 您可以在这篇博文中看到每个标志的作用:medium.com/@yair.kukielka/…
    【解决方案2】:

    我收到了很多这样的警告,而且我总是使用 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);
            }
        }
    

    【讨论】:

    • 与接受的答案效果相同,但由于 SuppressWarnings 注释而 +1
    • 你能简单解释一下这个模式吗?
    • 你能提供所有 HtmlCompact 可能在 git hub 上看起来很酷
    • @shareef 我会,但它实际上只是一个无聊的实用程序类,其中只有一个方法......
    【解决方案3】:

    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
    

    【讨论】:

    • 你能分享输入HTML吗?这将有助于更好地理解转换。
    • 我看到style属性没有实现,有没有办法实现?
    【解决方案4】:

    或者你可以使用androidx.core.text.HtmlCompat:

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

    HtmlCompat docs

    【讨论】:

    • 你甚至可以在 Android 5 上使用它?
    • @CDrosos 是的,它是支持库的一部分
    【解决方案5】:

    如果你有幸在 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()
    

    【讨论】:

    • 你可以通过删除Spannedreturn来保存打字
    【解决方案6】:

    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")
    

    【讨论】:

    • 你能简单解释一下这个模式吗?
    • 如果您希望 SDK 处理版本检查,请使用:HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
    【解决方案7】:

    如果您使用的是 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设备处理
    • 您可以将 if/else 替换为:HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY)
    【解决方案8】:

    来自官方文档:

    fromHtml(String) 方法在 API 级别 24 中已弃用。使用 fromHtml(String, int) 而是。

    1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVE toHtml(Spanned, int) 的选项:将由'\n' 分隔的连续文本行包裹在&lt;p&gt; 内 元素。

    2. TO_HTML_PARAGRAPH_LINES_INDIVIDUAL toHtml(Spanned, int) 的选项:将由 '\n' 分隔的每一行文本包裹在 &lt;p&gt;&lt;li&gt; 内 元素。

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

    【讨论】:

      【解决方案9】:

      只是为了扩展@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分支中弃用。所以这不会抑制除单个分支之外的所有方法。

      当 Google 决定在未来的某些 Android 版本中弃用 fromHtml(String source, int flags) 方法时,它会有所帮助。

      【讨论】:

        【解决方案10】:

        你可以使用

        //noinspection deprecation
        return Html.fromHtml(source);
        

        仅针对单个语句而不是整个方法禁止检查。

        【讨论】:

          【解决方案11】:

          这是我的解决方案。

           if (Build.VERSION.SDK_INT >= 24) {
                  holder.notificationTitle.setText(Html.fromHtml(notificationSucces.getMessage(), Html.FROM_HTML_MODE_LEGACY));
              } else {
                  holder.notificationTitle.setText(Html.fromHtml(notificationSucces.getMessage()));
          
              }
          

          【讨论】:

            【解决方案12】:

            只做一个函数:

            public Spanned fromHtml(String str){
              return Build.VERSION.SDK_INT >= 24 ? Html.fromHtml(str, Html.FROM_HTML_MODE_LEGACY) : Html.fromHtml(str);
            }
            

            【讨论】:

              【解决方案13】:

              框架类已被修改为需要一个标志来通知fromHtml() 如何处理换行符。这是在 Nougat 中添加的,仅涉及此类跨 Android 版本不兼容的挑战。

              我已经发布了一个兼容性库来标准化和向后移植该类,并包含更多元素和样式的回调:

              https://github.com/Pixplicity/HtmlCompat

              虽然它类似于框架的 Html 类,但需要进行一些签名更改以允许更多回调。这是来自 GitHub 页面的示例:

              Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0);
              // You may want to provide an ImageGetter, TagHandler and SpanCallback:
              //Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0,
              //        imageGetter, tagHandler, spanCallback);
              textView.setMovementMethod(LinkMovementMethod.getInstance());
              textView.setText(fromHtml);
              

              【讨论】:

              • 当我在使用 minSdkVersion 15targetSdkVersion 23 的应用程序上使用您的库时,values-v24.xml 出现构建错误:Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'. 您的库目标显然,API 级别 25。我还能怎么用?
              【解决方案14】:

              尝试以下方法来支持基本的 html 标签,包括 ul ol li 标签。 创建一个标签处理程序,如下所示

              import org.xml.sax.XMLReader;
              
              import android.app.Activity;
              import android.os.Bundle;
              import android.text.Editable;
              import android.text.Html;
              import android.text.Html.TagHandler;
              import android.util.Log;
              
              public class MyTagHandler implements TagHandler {
                  boolean first= true;
                  String parent=null;
                  int index=1;
                  @Override
                  public void handleTag(boolean opening, String tag, Editable output,
                                        XMLReader xmlReader) {
              
                      if(tag.equals("ul")) parent="ul";
                      else if(tag.equals("ol")) parent="ol";
                      if(tag.equals("li")){
                          if(parent.equals("ul")){
                              if(first){
                                  output.append("\n\t•");
                                  first= false;
                              }else{
                                  first = true;
                              }
                          }
                          else{
                              if(first){
                                  output.append("\n\t"+index+". ");
                                  first= false;
                                  index++;
                              }else{
                                  first = true;
                              }
                          }
                      }
                  }
              }
              

              在Activity上设置文字如下图

              @SuppressWarnings("deprecation")
                  public void init(){
                      try {
                          TextView help = (TextView) findViewById(R.id.help);
                          if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
                              help.setText(Html.fromHtml(getString(R.string.help_html),Html.FROM_HTML_MODE_LEGACY, null, new MyTagHandler()));
                          } else {
                              help.setText(Html.fromHtml(getString(R.string.help_html), null, new MyTagHandler()));
                          }
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
              
                  }
              

              资源字符串文件上的html文本为

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-10-05
                • 2018-12-16
                相关资源
                最近更新 更多