Como exibir HTML no TextView?


756

Eu tenho HTML simples :

<h2>Title</h2><br>
<p>description here</p>

Quero exibir o texto com estilo HTML TextView. Como fazer isso?


7
Deseja exibir ou omitir as tags?
DerMike 22/01

1

1
Se você está procurando uma solução de obsolescência, é só aqui stackoverflow.com/questions/37904739/...
crgarridos

Respostas:


1351

Você precisa Html.fromHtml()usar o HTML em suas cadeias XML. Simplesmente referenciar uma String com HTML em seu layout XML não funcionará.

Isto é o que você deve fazer:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>", Html.FROM_HTML_MODE_COMPACT));
} else { 
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>"));
}

7
h2por definição, cria muita margem em torno de si. e ptambém vem com alguma margem. se você não quiser essa lacuna, considere usar outros elementos html.
David Hedlund

10
Além disso, você pode colocar tags em XML, basta envolvê-las em colchetes CDATA.
31512 Gerard

3
Para quem quer que ele funcione com as tags ol / ul / li, confira esta solução: stackoverflow.com/a/3150456/1369016
Tiago

13
Isso deveria ser android.text.Html.fromHtml. Eu sei que a maioria dos IDEs irá corrigi-lo para você, mas para facilitar a leitura, é melhor conhecer os nomes dos pacotes.
Martin

14
@ Martin Eu não diria pela legibilidade, mas pela exaustividade . Os nomes totalmente qualificados da IMO usados ​​diretamente em códigos como este são menos legíveis que os nomes abreviados. Mas eu concordo com você sobre o fato de que uma resposta como esta deve fornecer o pacote (em uma nota lateral), que o ponto do link aqui;)
Joffrey

76

setText (Html.fromHtml (bodyData)) foi preterido após a API 24. Agora você deve fazer isso:

 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
      tvDocument.setText(Html.fromHtml(bodyData,Html.FROM_HTML_MODE_LEGACY));
 } else {
      tvDocument.setText(Html.fromHtml(bodyData));
 }

4
Por que usa FROM_HTML_MODE_LEGACY na API 24+?
Galcyurio 24/05/19

64

Dê uma olhada nisto: https://stackoverflow.com/a/8558249/450148

Também é muito bom !!

<resource>
    <string name="your_string">This is an <u>underline</u> text demo for TextView.</string>
</resources>

Funciona apenas para algumas tags.


12
Existe alguma lista de tags suportadas por esse método?
Mente

23
@mente De acordo com os códigos-fonte : <a>, <b>, <big>, <blockquote>, <br>, <cite>, <dfn> <div align = "...">, <em>, < tamanho da fonte = "..." color = "..." face = "..."> <h1-6>, <i>, <img src = "...">, <p>, <pequeno > <strike>, <strong>, <sub>, <sup>, <tt>, <u> (fonte: dzone.com/snippets/how-display-html-android )
JerabekJakub

@JerabekJakub, mas tome cuidado, se você quiser lidar com img, precisará implementar o Html.ImageGetter.
MiguelHincapieC

@ 0mahc0 quando se implementa img é possível definir o tamanho?
Joh

1
@ Oh, sim, é possível. Quando você está implementando .ImageGetter, existe um método chamado getDrawable (origem da string). Se você precisar de mais ajuda, crie uma pergunta e
marque-

41

Se você deseja configurá-lo através do xml sem nenhuma modificação no código java, poderá achar útil essa ideia. Basta chamar init do construtor e definir o texto como html

public class HTMLTextView extends TextView {
    ... constructors calling init...
    private void init(){
       setText(Html.fromHtml(getText().toString()));
    }    
}

xml:

<com.package.HTMLTextView
android:text="@string/about_item_1"/>

1
O que é '...'. Por favor, esclareça
GilbertS

25

Se você está tentando mostrar HTML a partir de um ID de recurso de sequência, a formatação pode não aparecer na tela. Se isso estiver acontecendo com você, tente usar as tags CDATA:

strings.xml:
<string name="sample_string"><![CDATA[<h2>Title</h2><br><p>Description here</p>]]></string>

...

MainActivity.java:
text.setText(Html.fromHtml(getString(R.string.sample_string));

Veja este post para mais detalhes.


Obrigado, isso fez isso por me- usando API 23.
XMAN

24

O código abaixo deu o melhor resultado para mim.

TextView myTextview = (TextView) findViewById(R.id.my_text_view);
htmltext = <your html (markup) character>;
Spanned sp = Html.fromHtml(htmltext);
myTextview.setText(sp);

13
String value = "<html> <a href=\"http://example.com/\">example.com</a> </html>";
    SiteLink= (TextView) findViewById(R.id.textViewSite);
    SiteLink.setText(Html.fromHtml(value));
    SiteLink.setMovementMethod(LinkMovementMethod.getInstance());

como você muda a cor da âncora?
EdmundYeung99

android: textColorLink = "color"
Pedro

isso irá colorir toda a textview para vermelho, mas se eu só quero as marcas de âncora, eu preciso embrulhar o tag <a> com tags <font> e adicionar cor lá
EdmundYeung99

11

Se você deseja exibir algum texto html e realmente não precisa de um TextView, pegue um WebViewe use-o da seguinte maneira:

String htmlText = ...;
webview.loadData(htmlText , "text/html; charset=UTF-8", null);

Isso também não o restringe a algumas tags html.


2
Enquanto esta é uma maneira muito útil para contornar o conjunto restrito de tags HTML, apoiado por TextView, tem a desvantagem de que não funciona bem com layout_height="wrap_content". Você precisará definir uma altura explícita ou match_parent.
Ridcully

3
webview é muito lento
Jackky777

11

A melhor abordagem para usar as seções CData para a sequência no arquivo strings.xml para obter uma exibição real do conteúdo html no TextView, o snippet de código abaixo, fornecerá a você uma idéia justa.

//in string.xml file
<string name="welcome_text"><![CDATA[<b>Welcome,</b> to the forthetyroprogrammers blog Logged in as:]]> %1$s.</string>

//and in Java code
String welcomStr=String.format(getString(R.string.welcome_text),username);
tvWelcomeUser.setText(Html.fromHtml(welcomStr));

A seção CData no texto da string mantém os dados da tag html intactos, mesmo após a formatação do texto usando o método String.format. Portanto, Html.fromHtml (str) funciona bem e você verá o texto em negrito na mensagem de boas-vindas.

Resultado:

Bem-vindo à sua loja de aplicativos de música favorita. Conectado como: nome de usuário


Obrigado, isso fez isso por me- usando API 23.
XMAN

obrigado, u salvou meu dia :) Apenas uma pequena adição: precisamos adicionar esta verificação ao código acima: if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.N) {// para 24 APIs e mais textView.setText ( Html.fromHtml (welcomStr, Html.FROM_HTML_OPTION_USE_CSS_COLORS)); } else {// ou para API antiga textView.setText (Html.fromHtml (welcomStr)); } O valor do segundo sinalizador de parâmetro para API> = 24 pode ser qualquer coisa conforme o requisito.
precisa saber é o seguinte


6

Gostaria também de sugerir o seguinte projeto: https://github.com/NightWhistler/HtmlSpanner

O uso é quase o mesmo que o conversor android padrão:

(new HtmlSpanner()).fromHtml()

Encontrei depois que eu já comecei pela própria implementação do conversor de html para spannable, porque o padrão Html.fromHtml não oferece flexibilidade suficiente sobre o controle de renderização e nem mesmo a possibilidade de usar fontes personalizadas do ttf


Estou recebendo o seguinte erro: Erro: (80, 13) Falha ao resolver: com.osbcp.cssparser: cssparser: 1.5 Como resolver isso?
Araju 18/08/19

6

Eu sei que esta pergunta é antiga. Outras respostas aqui sugerindo Html.fromHtml()método. Eu sugiro que você use HtmlCompat.fromHtml()do androidx.core.text.HtmlCompatpacote. Como esta é a versão compatível com versões anteriores doHtml classe.

Código de amostra:

import androidx.core.text.HtmlCompat;
import android.text.Spanned;
import android.widget.TextView;

String htmlString = "<h1>Hello World!</h1>";

Spanned spanned = HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT);

TextView tvOutput = (TextView) findViewById(R.id.text_view_id);

tvOutput.setText(spanned);

Dessa forma, você pode evitar a verificação da versão da API do Android e é fácil de usar (solução de linha única).


Como isso é diferente da methot antiga? Qual é a finalidade do modo html?
precisa saber é o seguinte

1
Estava procurando por algo assim. Obrigado :)
Subhrajyoti Sen 30/01

5

Uso simples Html.fromHtml("html string"). Isso vai funcionar. Se a string tiver tags como <h1>espaços, virão espaços. Mas não podemos eliminar esses espaços. Se você ainda quer remover os espaços, então você pode remover as tags na cadeia e, em seguida, passar a string para o método Html.fromHtml("html string");. Além disso, geralmente essas strings vêm do servidor (dinâmico), mas não frequentemente, se for o melhor passar a string como é para o método do que tentar remover as tags da string.


4
String value = html value ....
mTextView.setText(Html.fromHtml(value),TextView.BufferType.SPANNABLE)

4

Faça um método global como:

public static Spanned stripHtml(String html) {
            if (!TextUtils.isEmpty(html)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    return Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT);
                } else {
                    return Html.fromHtml(html);
                }
            }
            return null;
        }

Você também pode usá-lo em sua Atividade / Fragmento, como:

text_view.setText(stripHtml(htmlText));

3

Eu implementei isso usando o modo de exibição da web. No meu caso, eu tenho que carregar a imagem do URL junto com o texto na exibição de texto e isso funciona para mim.

WebView myWebView =new WebView(_context);
        String html = childText;
        String mime = "text/html";
        String encoding = "utf-8";
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.loadDataWithBaseURL(null, html, mime, encoding, null);

Para uma exibição adequada do UTF-8, você precisa definir o tipo MIME como "text / html; charset = UTF-8".
shawkinaw

3

Foi sugerido, através de várias respostas, o uso da classe de estrutura Html , conforme sugerido aqui, mas infelizmente essa classe possui um comportamento diferente em diferentes versões do Android e vários bugs não corrigidos , conforme demonstrado nas edições 214637 , 14778 , 235128 e 75953 .

Portanto, convém usar uma biblioteca de compatibilidade para padronizar e suportar a classe Html nas versões do Android, o que inclui mais retornos de chamada para elementos e estilo:

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

@MartijnPieters A resposta anteriormente fechada era uma duplicata de uma resposta a esta pergunta em relação à depreciação de um método de estrutura . Eu expandi o motivo pelo qual usar uma biblioteca de compatibilidade seria uma abordagem melhor. Eu não acho que seja razoável sinalizar as perguntas como duplicatas uma da outra, pois elas são claramente diferentes.
Paul Lammertsma

2

Sempre que você escrever uma visualização de texto personalizada, o recurso básico de texto de conjunto de HTML será desvanecido em alguns dos dispositivos.

Então, precisamos seguir os passos adicionais que fazem funcionar

public class CustomTextView extends TextView {

    public CustomTextView(..) {
        // other instructions
        setText(Html.fromHtml(getText().toString()));
    }
}

1
public class HtmlTextView extends AppCompatTextView {

public HtmlTextView(Context context) {
    super(context);
    init();
}

private void init(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        setText(Html.fromHtml(getText().toString(), Html.FROM_HTML_MODE_COMPACT));
    } else {
        setText(Html.fromHtml(getText().toString()));
    }
 }
}

atualização da resposta acima


1

Use o código abaixo para obter a solução:

textView.setText(fromHtml("<Your Html Text>"))

Método de Utitilty

public static Spanned fromHtml(String text)
{
    Spanned result;
    if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        result = Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY);
    } else {
        result = Html.fromHtml(text);
    }
    return result;
}

1

Criadas extensões do Kotlin para converter html de String -

fun String?.toHtml(): Spanned? {
    if (this.isNullOrEmpty()) return null
    return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_COMPACT)
}

0

Posso sugerir uma solução um tanto hacky, mas ainda genial! Eu peguei a ideia deste artigo e a adaptei para o Android. Basicamente, você usa WebViewae insere o HTML que deseja mostrar e editar em uma tag div editável. Dessa forma, quando o usuário toca noWebView no teclado, aparece e permite a edição. Eles apenas adicionam um pouco de JavaScript para recuperar o HTML editado e pronto!

Aqui está o código:

public class HtmlTextEditor extends WebView {

    class JsObject {
        // This field always keeps the latest edited text
        public String text;
        @JavascriptInterface
        public void textDidChange(String newText) {
            text = newText.replace("\n", "");
        }
    }

    private JsObject mJsObject;

    public HtmlTextEditor(Context context, AttributeSet attrs) {
        super(context, attrs);

        getSettings().setJavaScriptEnabled(true);
        mJsObject = new JsObject();
        addJavascriptInterface(mJsObject, "injectedObject");
        setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                loadUrl(
                        "javascript:(function() { " +
                            "    var editor = document.getElementById(\"editor\");" +
                            "    editor.addEventListener(\"input\", function() {" +
                            "        injectedObject.textDidChange(editor.innerHTML);" +
                            "    }, false)" +
                            "})()");
            }
        });
    }

    public void setText(String text) {
        if (text == null) { text = ""; }

        String editableHtmlTemplate = "<!DOCTYPE html>" + "<html>" + "<head>" + "<meta name=\"viewport\" content=\"initial-scale=1.0\" />" + "</head>" + "<body>" + "<div id=\"editor\" contenteditable=\"true\">___REPLACE___</div>" + "</body>" + "</html>";
        String editableHtml = editableHtmlTemplate.replace("___REPLACE___", text);
        loadData(editableHtml, "text/html; charset=utf-8", "UTF-8");
        // Init the text field in case it's read without editing the text before
        mJsObject.text = text;
    }

    public String getText() {
        return mJsObject.text;
    }
}

E aqui está o componente como uma essência.

Nota: Eu não precisava do retorno de chamada de alteração de altura da solução original, portanto, falta aqui, mas você pode adicioná-lo facilmente, se necessário.


0

Se você usa androidx.* classes em seu projeto, você deve usar HtmlCompat.fromHtml(text, flag). A fonte do método é:

@NonNull public static Spanned fromHtml(@NonNull String source, @FromHtmlFlags int flags) { if (Build.VERSION.SDK_INT >= 24) { return Html.fromHtml(source, flags); } //noinspection deprecation return Html.fromHtml(source); }

É uma maneira melhor do que Html.fromHtml, pois há menos código, apenas uma linha e a maneira recomendada de usá-lo.


0

Você pode usar a função de extensão Kotlin simples como esta:

fun TextView.setHtmlText(source: String) {
    this.text = HtmlCompat.fromHtml(source, HtmlCompat.FROM_HTML_MODE_LEGACY)
}

E uso:

textViewMessage.setHtmlText("Message: <b>Hello World</b>")

0

Basta usar:

String variable="StackOverflow";
textView.setText(Html.fromHtml("<b>Hello : </b>"+ variable));
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.