在Android N中不推荐使用Html.fromHtml


300

我正在使用Html.fromHtml中查看html TextView

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

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

什么/如何找到新的方法?

Answers:


616

update:正如下面提到的@Andy一样, Google已创建HtmlCompat了可以代替以下方法使用的Google 。将此依赖项添加implementation 'androidx.core:core:1.0.1 到应用程序的build.gradle文件中。确保您使用的是最新版本androidx.core:core

这使您可以使用:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

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

最初的答案: 在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类文档中阅读有关不同标志的更多信息。


2
零代表哪个标志?
ban-geoengineering

4
Html.FROM_HTML_MODE_LEGACY
ban-geoengineering

14
啊,等待类似HtmlCompat的出现
vanomart

12
在的//noinspection deprecation正下方添加注释else以避免棉绒警告也很有用。
泰德·霍普

1
你可以看到在这个博客帖子这些标志做:medium.com/@yair.kukielka/...
亚伊尔Kukielka

95

我有很多这样的警告,并且我总是使用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
效果与接受的答案相同,但由于SuppressWarnings注释而为+1
Stoycho Andreev

您能对此模式做些小的解释吗?
Ranjith Kumar

你能提供所有的HtmlCompact可能在git hub上看起来很酷

@shareef我会的,但实际上只是一个无聊的实用工具类,里面只有一个方法....
k2col

61

比较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标志


您还可以共享输入HTML吗?这将有助于更好地理解转换。
卡尔佩什·帕特尔

我看到样式属性未实现,有没有办法实现它们?
克里斯汀


25

如果您有幸在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

14

来自Html

这种方法被弃用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"));
        }

对于科特林

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

您能对此模式做些小的解释吗?
Ranjith Kumar

如果您想让SDK处理版本检查,请使用: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali,

8

来自官方文档:

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


8

如果您使用的是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)

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分支中。因此,这将不会抑制所有方法,而是会取消单个分支。

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


4

您可以使用

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

只检查单个语句而不检查整个方法。


2

框架类已被修改为需要一个标志来告知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。我怎么仍然可以使用它?
JJD

2

这是我的解决方案。

 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()));

    }

1

只是做一个功能:

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

-2

尝试以下操作以支持基本的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;
                }
            }
        }
    }
}

如下所示在“活动”上设置文本

@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文本为

<![CDATA [...原始html数据...]]>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.