Html.fromHtml deprecato in Android N


300

Sto usando Html.fromHtmlper visualizzare HTML in a TextView.

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

Ma Html.fromHtmlora è deprecato in Android N +

Cosa / Come posso trovare il nuovo modo di farlo?

Risposte:


616

aggiornamento : come @Andy menzionato di seguito ha creato Google HtmlCompatche può essere utilizzato al posto del metodo seguente. Aggiungi questa dipendenza implementation 'androidx.core:core:1.0.1 al file build.gradle della tua app. Assicurati di utilizzare l'ultima versione di androidx.core:core.

Questo ti permette di usare:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Puoi leggere ulteriori informazioni sui diversi flag nella documentazione di HtmlCompat

risposta originale: in Android N hanno introdotto un nuovo Html.fromHtmlmetodo. Html.fromHtmlora richiede un parametro aggiuntivo, denominato flags. Questo flag ti dà più controllo su come viene visualizzato il tuo HTML.

Su Android N e versioni successive dovresti utilizzare questo nuovo metodo. Il metodo precedente è obsoleto e potrebbe essere rimosso nelle future versioni di Android.

Puoi creare il tuo metodo Util che utilizzerà il vecchio metodo su versioni precedenti e il metodo più recente su Android N e versioni successive. Se non aggiungi una versione, verifica che l'app non funzionerà con versioni di Android inferiori. Puoi usare questo metodo nella tua classe 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_LEGACYSe lo desideri, puoi convertire il parametro in un parametro aggiuntivo. Questo ti dà più controllo su quale flag usare.

Puoi leggere ulteriori informazioni sui diversi flag nella documentazione della classe HTML


2
Quale bandiera rappresenta lo zero?
divieto di geoingegneria il

4
Html.FROM_HTML_MODE_LEGACY
divieto di geoingegneria il

14
ah, aspettando che appaia qualcosa come HtmlCompat
vanomart,

12
È anche utile aggiungere un //noinspection deprecationcommento appena sotto elseper evitare avvisi di lanugine.
Ted Hopp,

1
Puoi vedere cosa fanno ognuna di queste bandiere in questo post del blog: medium.com/@yair.kukielka/…
Yair Kukielka,

95

Ho ricevuto molti di questi avvisi e utilizzo sempre FROM_HTML_MODE_LEGACY, quindi ho creato una classe di supporto chiamata HtmlCompat contenente quanto segue:

   @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
Stesso effetto della risposta accettata, ma +1 a causa dell'annotazione SuppressWarnings
Stoycho Andreev,

Puoi dare una piccola spiegazione su questa modalità?
Ranjith Kumar il

potresti fornire tutto HtmlCompact potrebbe essere su git hub sembra bello
shareef

@shareef Lo farei, ma è davvero solo una noiosa classe di utilità con questo singolo metodo ...
k2col

61

Confronto dei flag di 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

DA_HTML BANDIERE


Puoi condividere anche HTML di input? Ciò aiuterebbe a comprendere meglio la conversione.
Kalpesh Patel,

Vedo che gli attributi di stile non sono implementati, c'è un modo per implementarli?
Christine,


25

Se sei abbastanza fortunato da sviluppare su Kotlin, basta creare una funzione di estensione:

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

E poi è così dolce usarlo ovunque:

yourTextView.text = anyString.toSpanned()

5
puoi salvare le digitazioni rimuovendo Spannedereturn
Minami il

14

fromHtml

Questo metodo è stato deprecato nel livello API 24 .

Dovresti usare FROM_HTML_MODE_LEGACY

Separare gli elementi a livello di blocco con linee vuote (due caratteri di nuova riga) in mezzo. Questo è il comportamento precedente prima di N.

Codice

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

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

Chiamata

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

Puoi dare una piccola spiegazione su questa modalità?
Ranjith Kumar il

se si desidera che SDK gestisca i controlli di versione, utilizzare: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali

8

Dal documento ufficiale:

fromHtml(String)il metodo è stato deprecato nel livello API 24. utilizzare fromHtml(String, int) invece.

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEOpzione per toHtml(Spanned, int): avvolgere righe consecutive di testo delimitate da elementi '\n'interni <p>.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALOpzione per toHtml(Spanned, int): avvolgere ogni riga di testo delimitata da '\n'all'interno di <p>un <li> elemento.

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


8

Se stai usando Kotlin , ho ottenuto questo risultato usando un'estensione 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))
    }
}

Quindi chiamalo come:

textView.htmlText(yourHtmlText)

5

Solo per estendere la risposta da @Rockney e @ k2col il codice migliorato può apparire come:

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

Dove il CompatUtils.isApiNonLowerThan:

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

La differenza è che non ci sono variabili locali extra e la deprecazione è solo in elsediramazione. Quindi questo non sopprimerà tutto il metodo ma il singolo ramo.

Può aiutare quando Google deciderà in alcune versioni future di Android di deprecare anche il fromHtml(String source, int flags)metodo.


4

Puoi usare

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

per sopprimere l'ispezione solo per una singola istruzione ma non per l'intero metodo.


2

La classe framework è stata modificata per richiedere un flag per informare su fromHtml()come elaborare le interruzioni di riga. Questo è stato aggiunto in Nougat e tocca solo la sfida delle incompatibilità di questa classe tra le versioni di Android.

Ho pubblicato una libreria di compatibilità per standardizzare e eseguire il backport della classe e includere più callback per elementi e stile:

https://github.com/Pixplicity/HtmlCompat

Sebbene sia simile alla classe Html del framework, sono state necessarie alcune modifiche alla firma per consentire più callback. Ecco l'esempio dalla pagina 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);

Quando utilizzo la tua libreria su un'app che utilizza minSdkVersion 15e targetSdkVersion 23ricevo un errore di build per valori-v24.xml : la Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.tua libreria ha come target il livello API 25, ovviamente. Come posso ancora usarlo?
JJD,

2

Ecco la mia soluzione

 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

basta fare una funzione:

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

0

Prova questa piccola riga di codice

HtmlCompat.fromHtml("Your html text",HtmlCompat.FROM_HTML_MODE_LEGACY)

-2

Prova quanto segue per supportare tag html di base tra cui tag ul ol li. Creare un gestore tag come mostrato di seguito

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

Imposta il testo su Attività come mostrato di seguito

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

    }

E testo HTML su file di stringhe di risorse come

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.