Html.fromHtml in Android N veraltet


300

Ich verwende Html.fromHtml, um HTML in einem anzuzeigen TextView.

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

Ist Html.fromHtmlaber jetzt in Android N + veraltet

Was / Wie finde ich den neuen Weg dazu?

Antworten:


616

Update : Wie @Andy unten erwähnt, hat Google erstellt HtmlCompat, das anstelle der unten beschriebenen Methode verwendet werden kann. Fügen Sie diese Abhängigkeit implementation 'androidx.core:core:1.0.1 der Datei build.gradle Ihrer App hinzu. Stellen Sie sicher, dass Sie die neueste Version von verwenden androidx.core:core.

Dies ermöglicht Ihnen Folgendes:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Weitere Informationen zu den verschiedenen Flags finden Sie in der HtmlCompat-Dokumentation

ursprüngliche Antwort: In Android N wurde eine neue Html.fromHtmlMethode eingeführt. Html.fromHtmlJetzt ist ein zusätzlicher Parameter mit dem Namen flags erforderlich. Dieses Flag gibt Ihnen mehr Kontrolle darüber, wie Ihr HTML angezeigt wird.

Unter Android N und höher sollten Sie diese neue Methode verwenden. Die ältere Methode ist veraltet und wird möglicherweise in zukünftigen Android-Versionen entfernt.

Sie können Ihre eigene Util-Methode erstellen, die die alte Methode bei älteren Versionen und die neuere Methode bei Android N und höher verwendet. Wenn Sie keine Versionsprüfung hinzufügen, wird Ihre App bei niedrigeren Android-Versionen beschädigt. Sie können diese Methode in Ihrer Util-Klasse verwenden.

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

Sie können das HTML.FROM_HTML_MODE_LEGACYin einen zusätzlichen Parameter konvertieren, wenn Sie möchten. Dies gibt Ihnen mehr Kontrolle darüber, welches Flag verwendet werden soll.

Weitere Informationen zu den verschiedenen Flags finden Sie in der Dokumentation zur HTML-Klasse


2
Welches Flag repräsentiert die Null?
Ban-Geoengineering

4
Html.FROM_HTML_MODE_LEGACY
Ban-Geoengineering

14
Ah, warten auf etwas wie HtmlCompat zu erscheinen
Vanomart

12
Es ist auch nützlich, einen //noinspection deprecationKommentar direkt unter hinzuzufügen else, um Flusenwarnungen zu vermeiden.
Ted Hopp

1
Sie können sehen, was jede dieser Flaggen in diesem Blog-Beitrag tut
Yair Kukielka

95

Ich hatte viele dieser Warnungen und verwende immer FROM_HTML_MODE_LEGACY, also habe ich eine Hilfsklasse namens HtmlCompat erstellt, die Folgendes enthält:

   @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
Gleicher Effekt wie die akzeptierte Antwort, aber +1 aufgrund der Annotation zu SuppressWarnings
Stoycho Andreev

Können Sie eine kleine Erklärung zu diesem Modus geben?
Ranjith Kumar

Könntest du alles bereitstellen, was HtmlCompact auf Git Hub sein kann
?

@shareef Ich würde, aber es ist wirklich nur eine langweilige Utility-Klasse mit dieser einzigen Methode darin ....
k2col

61

Vergleichen Sie die Flags von 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 FLAGS


Können Sie bitte auch Eingabe-HTML teilen? Dies würde zum besseren Verständnis der Konvertierung beitragen.
Kalpesh Patel

Ich sehe, dass die Stilattribute nicht implementiert sind. Gibt es eine Möglichkeit, sie zu implementieren?
Christine


25

Wenn Sie das Glück haben, sich auf Kotlin zu entwickeln, erstellen Sie einfach eine Erweiterungsfunktion:

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

Und dann ist es so süß, es überall zu benutzen:

yourTextView.text = anyString.toSpanned()

5
Sie können Eingaben speichern, indem Sie entfernen Spannedundreturn
Minami

14

fromHtml

Diese Methode wurde als veraltet in API - Ebene 24 .

Sie sollten FROM_HTML_MODE_LEGACY verwenden

Trennen Sie Elemente auf Blockebene mit Leerzeilen (zwei Zeilenumbruchzeichen) dazwischen. Dies ist das Legacy-Verhalten vor 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"));
        }

Für 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
    }

Anruf

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

Können Sie eine kleine Erklärung zu diesem Modus geben?
Ranjith Kumar

Wenn Sie möchten, dass das SDK Versionsprüfungen durchführt, verwenden Sie: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali,

8

Aus dem offiziellen Dokument:

fromHtml(String)Methode wurde in API Level 24 veraltet. Verwenden Sie fromHtml(String, int) stattdessen.

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEOption für toHtml(Spanned, int): Umschließen aufeinanderfolgender Textzeilen, die durch '\n'innere <p> Elemente begrenzt sind.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALOption für toHtml(Spanned, int): Umschließen Sie jede Textzeile, die durch '\n'ein <p>oder ein <li> Element begrenzt ist.

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


8

Wenn Sie Kotlin verwenden , habe ich dies mit einer Kotlin-Erweiterung erreicht:

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

Dann nenne es wie:

textView.htmlText(yourHtmlText)

5

Um die Antwort von @Rockney und @ k2col zu erweitern, kann der verbesserte Code folgendermaßen aussehen:

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

Wo die CompatUtils.isApiNonLowerThan:

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

Der Unterschied besteht darin, dass es keine zusätzliche lokale Variable gibt und die Abschreibung nur in der elseVerzweigung erfolgt. Dies unterdrückt also nicht alle Methoden außer einem einzelnen Zweig.

Es kann hilfreich sein, wenn Google in einigen zukünftigen Versionen von Android entscheidet, selbst die fromHtml(String source, int flags)Methode zu verwerfen .


4

Sie können verwenden

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

Inspektion nur für einzelne Anweisung, aber nicht für die gesamte Methode zu unterdrücken.


2

Die Framework-Klasse wurde so geändert, dass ein Flag zum Informieren erforderlich ist fromHtml() zur Verarbeitung von Zeilenumbrüchen zu erhalten. Dies wurde in Nougat hinzugefügt und berührt nur die Herausforderung von Inkompatibilitäten dieser Klasse über Android-Versionen hinweg.

Ich habe eine Kompatibilitätsbibliothek veröffentlicht, um die Klasse zu standardisieren und zurück zu portieren und weitere Rückrufe für Elemente und Stil zu enthalten:

https://github.com/Pixplicity/HtmlCompat

Obwohl es der HTML-Klasse des Frameworks ähnelt, waren einige Signaturänderungen erforderlich, um mehr Rückrufe zu ermöglichen. Hier ist das Beispiel von der GitHub-Seite:

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

Wenn ich Ihre Bibliothek in einer App verwende, die verwendet, minSdkVersion 15und targetSdkVersion 23ich einen Build-Fehler für values-v24.xml erhalte : Error:(3) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.Ihre Bibliothek zielt offensichtlich auf API-Level 25 ab. Wie kann ich es noch benutzen?
JJD

2

Hier ist meine Lösung.

 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

mach einfach eine Funktion:

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

-2

Versuchen Sie Folgendes, um grundlegende HTML-Tags einschließlich ul ol li-Tags zu unterstützen. Erstellen Sie einen Tag-Handler wie unten gezeigt

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

Stellen Sie den Text auf Aktivität wie unten gezeigt ein

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

    }

Und HTML-Text auf Ressourcen-String-Dateien als

<! [CDATA [... HTML-Rohdaten ...]]>

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.