Html.fromHtml deprecated in Android N

2019-01-02 19:51发布

I am using Html.fromHtml to view html in a TextView.

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

But Html.fromHtml is now deprecated in Android N+

What/How do I find the new way of doing this?

12条回答
心情的温度
2楼-- · 2019-01-02 20:39

Try the following to support basic html tags including ul ol li tags. Create a Tag handler as shown below

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

Set the text on Activity as shown below




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

        }

 

And html text on resource string files as

<![CDATA[ ...raw html data ...]] >

查看更多
爱死公子算了
3楼-- · 2019-01-02 20:41

If you are lucky enough to develop on Kotlin, just create an extension function:

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

And then it's so sweet to use it everywhere:

yourTextView.text = anyString.toSpanned()
查看更多
余生请多指教
4楼-- · 2019-01-02 20:41

If you're using Kotlin, I achieved this by using a Kotlin extension:

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

Then call it like:

textView.htmlText(yourHtmlText)
查看更多
只若初见
5楼-- · 2019-01-02 20:47

Or you can use androidx.core.text.HtmlCompat:

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

HtmlCompat docs

查看更多
与君花间醉酒
6楼-- · 2019-01-02 20:48

You have to add a version check and use the old method on Android M and below, on Android N and higher you should use the new method. If you don't add a version check your app will break on lower Android versions. You can use this method in your Util class.

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

Flag parameters:

public static final int FROM_HTML_MODE_COMPACT = 63;
public static final int FROM_HTML_MODE_LEGACY = 0;
public static final int FROM_HTML_OPTION_USE_CSS_COLORS = 256;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE = 32;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_DIV = 16;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_HEADING = 2;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST = 8;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM = 4;
public static final int FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH = 1;
public static final int TO_HTML_PARAGRAPH_LINES_CONSECUTIVE = 0;
public static final int TO_HTML_PARAGRAPH_LINES_INDIVIDUAL = 1;

You can read more about the different flags on the Html class documentation

查看更多
十年一品温如言
7楼-- · 2019-01-02 20:48

Just to extend the answer from @Rockney and @k2col the improved code can look like:

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

Where the CompatUtils.isApiNonLowerThan:

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

The difference is that there are no extra local variable and the deprecation is only in else branch. So this will not suppress all method but single branch.

It can help when the Google will decide in some future versions of Android to deprecate even the fromHtml(String source, int flags) method.

查看更多
登录 后发表回答