Html.fromHtml déconseillé dans Android N


300

J'utilise Html.fromHtmlpour afficher le html dans un fichier TextView.

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

Mais Html.fromHtmlest désormais obsolète dans Android N +

Quoi / Comment puis-je trouver la nouvelle façon de procéder?

Réponses:


616

mise à jour : comme @Andy mentionné ci-dessous, Google a créé HtmlCompatce qui peut être utilisé à la place de la méthode ci-dessous. Ajoutez cette dépendance implementation 'androidx.core:core:1.0.1 au fichier build.gradle de votre application. Assurez-vous d'utiliser la dernière version de androidx.core:core.

Cela vous permet d'utiliser:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Vous pouvez en savoir plus sur les différents drapeaux sur la documentation HtmlCompat

réponse originale: dans Android N, ils ont introduit une nouvelle Html.fromHtmlméthode. Html.fromHtmlnécessite désormais un paramètre supplémentaire, nommé flags. Cet indicateur vous donne plus de contrôle sur la façon dont votre code HTML s'affiche.

Sur Android N et supérieur, vous devez utiliser cette nouvelle méthode. L'ancienne méthode est obsolète et peut être supprimée dans les futures versions d'Android.

Vous pouvez créer votre propre méthode Util qui utilisera l'ancienne méthode sur les anciennes versions et la nouvelle méthode sur Android N et supérieur. Si vous n'ajoutez pas de version, vérifiez que votre application s'arrêtera sur les versions inférieures d'Android. Vous pouvez utiliser cette méthode dans votre 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);
    }
}

Vous pouvez convertir le HTML.FROM_HTML_MODE_LEGACYen un paramètre supplémentaire si vous le souhaitez. Cela vous donne plus de contrôle sur le drapeau à utiliser.

Vous pouvez en savoir plus sur les différents indicateurs dans la documentation de la classe Html


2
Quel drapeau représente le zéro?
ban-geoengineering

4
Html.FROM_HTML_MODE_LEGACY
ban-geoengineering

14
ah, en attendant que quelque chose comme HtmlCompat apparaisse
vanomart

12
Il est également utile d'ajouter un //noinspection deprecationcommentaire juste sous le elsepour éviter les avertissements de peluches.
Ted Hopp du

1
Vous pouvez voir ce que chacun de ces drapeaux fait dans cet article de blog: medium.com/@yair.kukielka/…
Yair Kukielka

95

J'ai eu beaucoup de ces avertissements et j'utilise toujours FROM_HTML_MODE_LEGACY, j'ai donc créé une classe d'assistance appelée HtmlCompat contenant les éléments suivants:

   @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
Même effet que la réponse acceptée, mais +1 en raison de l'annotation SuppressWarnings
Stoycho Andreev

Pouvez-vous donner une petite explication sur ce mode?
Ranjith Kumar

pourriez-vous fournir tout HtmlCompact peut être sur git hub, il a l'air cool
shareef

@shareef je le ferais mais c'est vraiment juste une classe utilitaire ennuyeuse avec cette seule méthode dedans ....
k2col

61

Comparaison des drapeaux de 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

DRAPEAUX FROM_HTML


Pouvez-vous également partager le code HTML d'entrée? Cela aiderait à mieux comprendre la conversion.
Kalpesh Patel

Je vois que les attributs de style ne sont pas implémentés, existe-t-il un moyen de les implémenter?
Christine


25

Si vous avez la chance de développer sur Kotlin, créez simplement une fonction d'extension:

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

Et puis c'est tellement agréable de l'utiliser partout:

yourTextView.text = anyString.toSpanned()

5
vous pouvez enregistrer les saisies en supprimant Spannedetreturn
Minami

14

fromHtml

Cette méthode était obsolète au niveau de l'API 24 .

Vous devez utiliser FROM_HTML_MODE_LEGACY

Éléments séparés au niveau du bloc avec des lignes vides (deux caractères de nouvelle ligne) entre les deux. Il s'agit du comportement hérité avant N.

Code

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

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

Appel

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

Pouvez-vous donner une petite explication sur ce mode?
Ranjith Kumar

si vous voulez que le SDK gère les vérifications de version, utilisez: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali

8

Du document officiel:

fromHtml(String)est devenue obsolète dans l'API niveau 24. utilisez-la à la fromHtml(String, int) place.

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEOption pour toHtml(Spanned, int): Envelopper des lignes de texte consécutives délimitées par des éléments '\n'intérieurs <p>.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALOption pour toHtml(Spanned, int): Envelopper chaque ligne de texte délimitée par '\n'un <p>ou un <li> élément.

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


8

Si vous utilisez Kotlin , j'ai atteint cet objectif en utilisant une extension 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))
    }
}

Ensuite, appelez-le comme:

textView.htmlText(yourHtmlText)

5

Juste pour étendre la réponse de @Rockney et @ k2col, le code amélioré peut ressembler à:

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

Où le CompatUtils.isApiNonLowerThan:

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

La différence est qu'il n'y a pas de variable locale supplémentaire et que la dépréciation est uniquement en elsebranche. Ainsi, cela ne supprimera pas toutes les méthodes, mais une seule branche.

Cela peut aider lorsque Google décidera dans certaines futures versions d'Android de déconseiller même la fromHtml(String source, int flags)méthode.


4

Vous pouvez utiliser

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

pour supprimer l'inspection juste pour une seule déclaration mais pas pour toute la méthode.


2

La classe d'infrastructure a été modifiée pour exiger un indicateur pour indiquer fromHtml()comment traiter les sauts de ligne. Cela a été ajouté dans Nougat, et ne touche que le défi des incompatibilités de cette classe entre les versions d'Android.

J'ai publié une bibliothèque de compatibilité pour standardiser et rétroporter la classe et inclure plus de rappels pour les éléments et le style:

https://github.com/Pixplicity/HtmlCompat

Bien qu'elle soit similaire à la classe Html du framework, certaines modifications de signature ont été nécessaires pour autoriser plus de rappels. Voici l'exemple de la page 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);

Lorsque j'utilise votre bibliothèque sur une application qui utilise minSdkVersion 15et targetSdkVersion 23que j'obtiens une erreur de génération pour 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'.votre bibliothèque cible le niveau 25 de l'API, évidemment. Comment puis-je encore l'utiliser?
JJD

2

Voici ma solution.

 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

faites juste une fonction:

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

0

Essayez cette petite ligne de code

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

-2

Essayez ce qui suit pour prendre en charge les balises html de base, y compris les balises ul ol li. Créez un gestionnaire de balises comme indiqué ci-dessous

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

Définissez le texte sur l'activité comme indiqué ci-dessous

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

    }

Et le texte html sur les fichiers de chaînes de ressources comme

<! [CDATA [... données html brutes ...]]>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.