Html.fromHtml en desuso en Android N


300

Estoy usando Html.fromHtmlpara ver html en a TextView.

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

Pero Html.fromHtmlahora está en desuso en Android N +

¿Qué / cómo encuentro la nueva forma de hacer esto?

Respuestas:


616

actualización : como @Andy menciona a continuación, Google ha creado lo HtmlCompatque se puede usar en lugar del método a continuación. Agregue esta dependencia implementation 'androidx.core:core:1.0.1 al archivo build.gradle de su aplicación. Asegúrate de usar la última versión de androidx.core:core.

Esto le permite usar:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Puede leer más acerca de los diferentes indicadores en la documentación HtmlCompat

respuesta original: en Android N introdujeron un nuevo Html.fromHtmlmétodo. Html.fromHtmlahora requiere un parámetro adicional, llamado flags. Esta bandera te da más control sobre cómo se muestra tu HTML.

En Android N y superior, debe usar este nuevo método. El método anterior está en desuso y puede eliminarse en las futuras versiones de Android.

Puede crear su propio método Util que utilizará el método anterior en versiones anteriores y el método más nuevo en Android N y superior. Si no agrega una versión, verifique que su aplicación se rompa en versiones inferiores de Android. Puede usar este método en su clase 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);
    }
}

Puede convertirlo HTML.FROM_HTML_MODE_LEGACYen un parámetro adicional si lo desea. Esto le da más control sobre qué bandera usar.

Puede leer más sobre los diferentes indicadores en la documentación de la clase Html


2
¿Qué bandera representa el cero?
prohibición de geoingeniería

44
Html.FROM_HTML_MODE_LEGACY
prohibición de geoingeniería

14
ah, esperando que aparezca algo como HtmlCompat
vanomart

12
También es útil agregar un //noinspection deprecationcomentario justo debajo de elsepara evitar advertencias de pelusa.
Ted Hopp

1
Puede ver lo que cada una de estas banderas hace en esta publicación de blog: medium.com/@yair.kukielka/…
Yair Kukielka

95

Tenía muchas de estas advertencias y siempre uso FROM_HTML_MODE_LEGACY, así que hice una clase auxiliar llamada HtmlCompat que contiene lo siguiente:

   @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
Mismo efecto que la respuesta aceptada, pero +1 debido a la anotación SuppressWarnings
Stoycho Andreev

¿Puedes dar una pequeña explicación sobre este modo?
Ranjith Kumar

podría proporcionar todo HtmlCompact puede estar en git hub se ve bien
shareef

@shareef Lo haría, pero en realidad es solo una clase de utilidad aburrida con este método único ...
k2col

61

Comparación de las banderas 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

BANDERAS FROM_HTML


¿Puedes compartir el HTML de entrada también? Esto ayudaría a comprender mejor la conversión.
Kalpesh Patel

Veo que los atributos de estilo no están implementados, ¿hay alguna manera de implementarlos?
Christine


25

Si tiene la suerte de desarrollar en Kotlin, simplemente cree una función de extensión:

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

Y luego es tan dulce usarlo en todas partes:

yourTextView.text = anyString.toSpanned()

55
puede guardar los tipos por eliminar Spannedyreturn
Minami

14

fromHtml

Este método fue desaprobado en el nivel 24 de API .

Deberías usar FROM_HTML_MODE_LEGACY

Elementos separados a nivel de bloque con líneas en blanco (dos caracteres de nueva línea) en el medio. Este es el comportamiento heredado anterior a N.

Código

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

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

Llamada

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

¿Puedes dar una pequeña explicación sobre este modo?
Ranjith Kumar

si desea que SDK maneje las verificaciones de versión, use: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
Wajid Ali

8

Del documento oficial:

fromHtml(String)el método fue desaprobado en el nivel 24 de API. en su fromHtml(String, int) lugar, úselo.

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEOpción para toHtml(Spanned, int): Ajustar líneas consecutivas de texto delimitadas por elementos '\n'internos <p>.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALOpción para toHtml(Spanned, int): Ajustar cada línea de texto delimitada por '\n'dentro de <p>un <li> elemento.

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


8

Si estás usando Kotlin , lo logré usando una extensión de 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))
    }
}

Entonces llámalo como:

textView.htmlText(yourHtmlText)

5

Solo para extender la respuesta de @Rockney y @ k2col, el código mejorado puede verse así:

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

Donde el CompatUtils.isApiNonLowerThan:

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

La diferencia es que no hay variables locales adicionales y la degradación es solo en else rama. Por lo tanto, esto no suprimirá todos los métodos excepto una sola rama.

Puede ayudar cuando Google decida en algunas versiones futuras de Android desaprobar incluso el fromHtml(String source, int flags)método.


4

Puedes usar

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

para suprimir la inspección solo para una sola declaración pero no todo el método.


2

La clase de marco se ha modificado para requerir un indicador para informar fromHtml()cómo procesar saltos de línea. Esto se agregó en Nougat, y solo toca el desafío de las incompatibilidades de esta clase en todas las versiones de Android.

He publicado una biblioteca de compatibilidad para estandarizar y respaldar la clase e incluir más devoluciones de llamada para elementos y estilo:

https://github.com/Pixplicity/HtmlCompat

Si bien es similar a la clase Html del marco, se requirieron algunos cambios de firma para permitir más devoluciones de llamada. Aquí está la muestra de la página de 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);

Cuando uso su biblioteca en una aplicación que usa minSdkVersion 15y targetSdkVersion 23obtengo un error de compilación para 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'.su biblioteca apunta al nivel 25 de API, obviamente. ¿Cómo puedo seguir usándolo?
JJD

2

Aquí está mi solución.

 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

solo haz una función:

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

0

Prueba esta pequeña línea de código

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

-2

Pruebe lo siguiente para admitir etiquetas html básicas, incluidas las etiquetas ul ol li. Cree un controlador de etiquetas como se muestra a continuación

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

Establezca el texto en Actividad como se muestra a continuación

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

    }

Y texto html en archivos de cadena de recursos como

<! [CDATA [... datos html sin procesar ...]]>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.