Html.fromHtml descontinuado no Android N


300

Eu estou usando Html.fromHtmlpara visualizar html em um TextView.

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

Mas Html.fromHtmlagora está obsoleto no Android N +

O que / como encontro a nova maneira de fazer isso?

Respostas:


616

update : como @ Andy mencionado abaixo, o Google criou o HtmlCompatque pode ser usado em vez do método abaixo. Adicione essa dependência implementation 'androidx.core:core:1.0.1 ao arquivo build.gradle do seu aplicativo. Certifique-se de usar a versão mais recente do androidx.core:core.

Isso permite que você use:

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY);

Você pode ler mais sobre os diferentes sinalizadores na documentação HtmlCompat

resposta original: No Android N, eles introduziram um novo Html.fromHtmlmétodo. Html.fromHtmlagora requer um parâmetro adicional, chamado flags. Esse sinalizador oferece mais controle sobre como o HTML é exibido.

No Android N e acima, você deve usar esse novo método. O método mais antigo está obsoleto e pode ser removido nas futuras versões do Android.

Você pode criar seu próprio método Util, que usará o método antigo em versões mais antigas e o mais recente no Android N e acima. Se você não adicionar uma versão, verifique se o aplicativo será interrompido nas versões inferiores do Android. Você pode usar esse método na sua 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);
    }
}

Você pode converter o HTML.FROM_HTML_MODE_LEGACYparâmetro em um parâmetro adicional, se desejar. Isso lhe dá mais controle sobre qual sinalizador usar.

Você pode ler mais sobre os diferentes sinalizadores na documentação da classe Html


2
Qual sinalizador representa o zero?
— ban-geoengineering

4
Html.FROM_HTML_MODE_LEGACY
— ban-geoengineering

14
ah, à espera de algo como HtmlCompat a aparecer
— vanomart

12
Também é útil adicionar um //noinspection deprecationcomentário logo abaixo do elsepara evitar avisos de fiapos.
— Ted Hopp

1
Você pode ver o que cada uma dessas bandeiras fazer neste post: medium.com/@yair.kukielka/...
— Yair Kukielka

95

Eu tinha muitos desses avisos e sempre uso FROM_HTML_MODE_LEGACY, então criei uma classe auxiliar chamada HtmlCompat contendo o seguinte:

   @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
Mesmo efeito como a resposta aceita, mas uma causa de SuppressWarnings anotação
— Stoycho Andreev

Você pode dar uma pequena explicação sobre esse modo?
— precisa

você poderia fornecer todos HTMLCompact pode estar no hub git ele parece legal
— shareef

@shareef eu iria, mas é realmente apenas uma classe de utilitário chato com este método único nele ....
— k2col

61

Compare as bandeiras 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

BANDEIRAS FROM_HTML


Você também pode compartilhar HTML de entrada? Isso ajudaria a entender melhor a conversão.
— Kalpesh Patel

Vejo que os atributos de estilo não são implementados, existe uma maneira de implementá-los?
— Christine


25

Se você tiver sorte o suficiente para desenvolver no Kotlin, basta criar uma função de extensão:

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 é tão bom usá-lo em qualquer lugar:

yourTextView.text = anyString.toSpanned()

5
você pode salvar digitações removendo Spannedereturn
— Minami

14

fromHtml

Este método foi preterido no nível da API 24 .

Você deve usar FROM_HTML_MODE_LEGACY

Separe os elementos no nível do bloco com linhas em branco (dois caracteres de nova linha) no meio. Esse é o comportamento herdado 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
    }

Ligar

 txt_OBJ.text  = setTextHTML("IIT Amiyo")

Você pode dar uma pequena explicação sobre esse modo?
— precisa

se você quiser que o SDK manipule verificações de versão, use: HtmlCompat.fromHtml("textWithHtmlTags", HtmlCompat.FROM_HTML_MODE_LEGACY)
— Wajid Ali

8

Do documento oficial:

fromHtml(String)O método foi preterido no nível 24 da API fromHtml(String, int) .

  1. TO_HTML_PARAGRAPH_LINES_CONSECUTIVEOpção para toHtml(Spanned, int): Quebrar linhas consecutivas de texto delimitadas por elementos '\n'internos <p>.

  2. TO_HTML_PARAGRAPH_LINES_INDIVIDUALOpção para toHtml(Spanned, int): quebrar cada linha de texto delimitada por '\n'um <p>ou um <li> elemento.

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


8

Se você estiver usando o Kotlin , consegui isso usando uma extensão do 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))
    }
}

Então chame assim:

textView.htmlText(yourHtmlText)

5

Apenas para estender a resposta de @Rockney e @ k2col, o código aprimorado pode se parecer com:

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

Onde CompatUtils.isApiNonLowerThan:

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

A diferença é que não há variável local extra e a depreciação ocorre apenas em else ramificação. Portanto, isso não suprimirá todo método, exceto uma ramificação única.

Pode ajudar quando o Google decidir em algumas versões futuras do Android descontinuar o fromHtml(String source, int flags)método.


4

Você pode usar

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

suprimir a inspeção apenas para uma única declaração, mas não para todo o método.


2

A classe de estrutura foi modificada para exigir um sinalizador para informar fromHtml()como processar quebras de linha. Isso foi adicionado ao Nougat e aborda apenas o desafio das incompatibilidades dessa classe nas versões do Android.

Publiquei uma biblioteca de compatibilidade para padronizar e suportar a classe e incluir mais retornos de chamada para elementos e estilo:

https://github.com/Pixplicity/HtmlCompat

Embora seja semelhante à classe Html da estrutura, algumas alterações de assinatura foram necessárias para permitir mais retornos de chamada. Aqui está o exemplo da página do 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 uso sua biblioteca em um aplicativo que usa minSdkVersion 15e targetSdkVersion 23recebo um erro de construção 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'.Sua biblioteca é direcionada ao nível 25 da API, obviamente. Como ainda posso usá-lo?
— JJD

2

Aqui está a minha solução.

 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 fazer uma função:

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

-2

Tente o seguinte para oferecer suporte a tags html básicas, incluindo tags ul ol li. Crie um manipulador de tags, como mostrado abaixo

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

Defina o texto em Atividade, como mostrado abaixo

@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 texto html em arquivos de cadeia de recursos como

<! [CDATA [... dados html brutos ...]]>

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.