ChatGPT解决这个技术问题 Extra ChatGPT

Android N 中不推荐使用 Html.fromHtml

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

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

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

什么/我如何找到这样做的新方法?


R
Rockney

更新:作为 @Andy mentioned below,Google 已经创建了 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/…
k
k2col

我有很多这样的警告,而且我总是使用 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 我会,但它真的只是一个无聊的实用程序类,里面有这个单一的方法......
您也可以只使用 HtmlCompat 并避免检查 Android 版本。
X
Xan

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

https://i.stack.imgur.com/kitpt.png


你也可以分享输入HTML吗?这将有助于更好地理解转换。
我看到样式属性没有实现,有没有办法实现呢?
O
Ondřej Z

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

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

HtmlCompat docs


您甚至可以在 Android 5 上使用它吗?
@CDrosos 是的,它是支持库的一部分
L
Leonid Ustenko

如果你有幸在 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 来保存输入
I
IntelliJ Amiya

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

对于科特林

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)
D
David Jarvis

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

来自官方文档:

在 API 级别 24 中不推荐使用 fromHtml(String) 方法。请改用 fromHtml(String, int)。 toHtml(Spanned, int) 的 TO_HTML_PARAGRAPH_LINES_CONSECUTIVE 选项:在

元素内换行以 '\n' 分隔的连续文本行。 toHtml(Spanned, int) 的 TO_HTML_PARAGRAPH_LINES_INDIVIDUAL 选项:将由 '\n' 分隔的每一行文本包装在

  • 元素内。

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


  • j
    jakubbialkowski

    只是为了扩展@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) 方法时,它会有所帮助。


    N
    Nikolay Tsigouro

    您可以使用

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

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


    p
    pavel

    这是我的解决方案。

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

    R
    ROHIT LIEN

    只是做一个功能:

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

    为什么不FROM_HTML_MODE_COMPACT
    P
    Paul Lammertsma

    框架类已修改为需要一个标志来通知 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 为目标。我怎么还能使用它?
    R
    Rockney

    尝试以下方法来支持基本的 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 文本作为