¿Cómo mostrar HTML en TextView?

Respuestas:

1352

Debe usar Html.fromHtml()para usar HTML en sus cadenas XML. Simplemente hacer referencia a una Cadena con HTML en su diseño XML no funcionará.

Esto es lo que debes hacer:

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>"));
}
Johnny Five
fuente
77
h2por definición crea mucho margen a su alrededor. y ptambién viene con cierto margen. Si no desea la brecha, puede considerar usar otros elementos html.
David Hedlund el
10
Kostadin, puede poner etiquetas en XML, solo necesita envolverlas entre corchetes CDATA.
Gerard
3
Para aquellos que desean que funcione con las etiquetas ol / ul / li, consulte esta solución: stackoverflow.com/a/3150456/1369016
Tiago
14
Eso debería ser android.text.Html.fromHtml. Sé que la mayoría de los IDEs lo arreglarán por usted, pero para facilitar la lectura, es mejor conocer los nombres de los paquetes.
Martin
14
@ Martin, no diría por legibilidad sino por exhaustividad . Los nombres totalmente calificados de la OMI utilizados directamente en código como este son menos legibles que los nombres cortos. Pero estoy de acuerdo con usted en el hecho de que una respuesta como esta debería proporcionar el paquete (en una nota al margen), que es el punto del enlace aquí;)
Joffrey
76

setText (Html.fromHtml (bodyData)) está en desuso después de la API 24. Ahora debe hacer esto:

 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));
 }
Shohan Ahmed Sijan
fuente
44
¿Por qué usa FROM_HTML_MODE_LEGACY en API 24+?
galcyurio
64

Echa un vistazo a esto: https://stackoverflow.com/a/8558249/450148

¡También es bastante bueno!

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

Funciona solo para algunas etiquetas.

Felipe Micaroni Lalli
fuente
12
¿Hay alguna lista de etiquetas compatibles con este método?
mente
23
@mente Según los códigos fuente : <a>, <b>, <big>, <blockquote>, <br>, <cite>, <dfn> <div align = "...">, <em>, < font size = "..." color = "..." face = "..."> <h1-6>, <i>, <img src = "...">, <p>, <small > <strike>, <strong>, <sub>, <sup>, <tt>, <u> (fuente: dzone.com/snippets/how-display-html-android )
JerabekJakub
@JerabekJakub pero ten cuidado, si vas a manejar img tienes que implementar Html.ImageGetter.
MiguelHincapieC
@ 0mahc0 cuando uno implementa img, ¿es posible establecer el tamaño?
Joh
1
@Joh sí, es posible. Cuando implementa .ImageGetter, hay un método llamado getDrawable (fuente de cadena). Si necesitas más ayuda, crea una pregunta y etiquétame, te daré un ejemplo;)
MiguelHincapieC
41

Si desea poder configurarlo a través de xml sin ninguna modificación en el código de Java, puede encontrar esta idea útil. Simplemente llame a init desde el constructor y configure el 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"/>
usuario1299412
fuente
1
¿Qué es '...'? Por favor aclare
GilbertS
25

Si está intentando mostrar HTML desde una identificación de recurso de cadena, es posible que el formato no se muestre en la pantalla. Si eso le sucede, intente usar etiquetas CDATA en su lugar:

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

Vea esta publicación para más detalles.

Phileo99
fuente
Gracias, esto lo hizo por mí, usando API 23.
XMAN
24

El siguiente código me dio el mejor resultado.

TextView myTextview = (TextView) findViewById(R.id.my_text_view);
htmltext = <your html (markup) character>;
Spanned sp = Html.fromHtml(htmltext);
myTextview.setText(sp);
Rajiv Manivannan
fuente
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());
Pedro
fuente
¿Cómo se cambia el color del ancla?
EdmundYeung99
android: textColorLink = "color"
Pedro
esto coloreará toda la vista de texto a rojo, pero si solo quiero las etiquetas de anclaje, necesito envolver la etiqueta <a> con etiquetas <font> y agregar color allí
EdmundYeung99
11

Si solo desea mostrar texto html y realmente no necesita un TextView, entonces tome un WebViewy úselo como sigue:

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

Esto tampoco lo restringe a unas pocas etiquetas html.

prom85
fuente
2
Si bien esta es una manera muy útil para moverse por el conjunto restringido de etiquetas HTML, con el apoyo de Vista de Texto, tiene el inconveniente de que no funciona bien con layout_height="wrap_content". Tendrás que establecer una altura explícita o match_parent en su lugar.
Ridcully
3
webview es muy lento
Jackky777
11

El mejor enfoque para usar secciones CData para la cadena en el archivo strings.xml para obtener una visualización real del contenido html en TextView, el fragmento de código a continuación le dará la idea 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));

La sección CData en el texto de cadena mantiene intactos los datos de la etiqueta html incluso después de formatear el texto usando el método String.format. Entonces, Html.fromHtml (str) funciona bien y verá el texto en negrita en el mensaje de bienvenida.

Salida:

Bienvenido, a tu tienda de aplicaciones de música favorita. Conectado como: nombre de usuario

Rajendhiran Easu
fuente
Gracias, esto lo hizo por mí, usando la API 23.
XMAN
gracias, me salvaste el día :) Solo una pequeña adición: necesitamos agregar esta verificación al código anterior: if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.N) {// para 24 api y más textView.setText ( Html.fromHtml (welcomStr, Html.FROM_HTML_OPTION_USE_CSS_COLORS)); } else {// o para una API anterior textView.setText (Html.fromHtml (welcomStr)); }. El valor para el segundo indicador de parámetro para API> = 24 puede ser cualquier cosa según el requisito.
AndroidGuy
6

También me gustaría sugerir el siguiente proyecto: https://github.com/NightWhistler/HtmlSpanner

El uso es casi el mismo que el convertidor de Android predeterminado:

(new HtmlSpanner()).fromHtml()

Lo encontré después de que ya comencé con la implementación propia del convertidor html a spannable, porque Html.fromHtml estándar no proporciona suficiente flexibilidad sobre el control de representación e incluso no hay posibilidad de usar fuentes personalizadas desde ttf

Fedotchenco Denis
fuente
Recibo el siguiente error: Error: (80, 13) Error al resolver: com.osbcp.cssparser: cssparser: 1.5 ¿Cómo resuelvo esto?
Araju
6

Sé que esta pregunta es vieja. Otras respuestas aquí sugieren Html.fromHtml()método. Te sugiero que uses HtmlCompat.fromHtml()del androidx.core.text.HtmlCompatpaquete. Como esta es una versión de Htmlclase compatible con versiones anteriores .

Código de muestra:

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

De esta manera, puede evitar la verificación de la versión de la API de Android y es fácil de usar (solución de línea única).

Shashanth
fuente
¿Cómo es eso diferente al viejo methot? ¿Cuál es el propósito del modo html?
user1209216
1
Estaba buscando algo como esto. Gracias :)
Subhrajyoti Sen
5

Uso simple Html.fromHtml("html string"). Esto funcionará Si la cadena tiene etiquetas como <h1>entonces vendrán espacios. Pero no podemos eliminar esos espacios. Si aún desea eliminar los espacios, puede eliminar las etiquetas en la cadena y luego pasar la cadena al método Html.fromHtml("html string");. También, en general, estas cadenas provienen del servidor (dinámico), pero no con frecuencia, si es el caso, es mejor pasar la cadena como está al método que intentar eliminar las etiquetas de la cadena.

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

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

También puede usarlo en su Actividad / Fragmento como:

text_view.setText(stripHtml(htmlText));
Shylendra Madda
fuente
3

He implementado esto usando la vista web. En mi caso, tengo que cargar la imagen de la URL junto con el texto en la vista de texto y esto funciona para mí.

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);
Asesino
fuente
Para una visualización adecuada de UTF-8, debe establecer el tipo MIME en "text / html; charset = UTF-8".
shawkinaw
3

Se ha sugerido a través de varias respuestas usar la clase de marco Html como se sugiere aquí, pero desafortunadamente esta clase tiene un comportamiento diferente en diferentes versiones de Android y varios errores no solucionados, como se demuestra en los números 214637 , 14778 , 235128 y 75953 .

Por lo tanto, es posible que desee utilizar una biblioteca de compatibilidad para estandarizar y respaldar la clase Html en las versiones de Android que incluye más devoluciones de llamada para elementos y estilo:

Proyecto Github 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);
Paul Lammertsma
fuente
@MartijnPieters La respuesta previamente cerrada era un duplicado de una respuesta a esta pregunta en relación con la depreciación de un método de marco . He ampliado la razón por la que usar una biblioteca de compatibilidad sería un mejor enfoque. No creo que sea razonable marcar cualquiera de las preguntas como duplicadas entre sí, ya que son claramente diferentes.
Paul Lammertsma
2

Cada vez que escriba una vista de texto personalizada, la función de texto del conjunto HTML básico desaparecerá de algunos de los dispositivos.

Por lo tanto, debemos hacer los siguientes pasos adicionales: hacer que funcione

public class CustomTextView extends TextView {

    public CustomTextView(..) {
        // other instructions
        setText(Html.fromHtml(getText().toString()));
    }
}
Vinayak
fuente
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()));
    }
 }
}

actualización de la respuesta anterior

Isaac Sekamatte
fuente
1

Use el siguiente código para obtener la solución:

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

Método de utilería

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;
}
Somesh Kumar
fuente
1

Creé extensiones de Kotlin para convertir html de String -

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

¿Puedo sugerir una solución un tanto hacky pero genial? Obtuve la idea de este artículo y la adapté para Android. Básicamente, usa WebVieway inserta el HTML que desea mostrar y editar en una etiqueta div editable. De esta forma, cuando el usuario toca WebViewel teclado, aparece el teclado y permite la edición. ¡Simplemente agregue algo de JavaScript para recuperar el HTML editado y listo!

Aquí está el 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;
    }
}

Y aquí está el componente como un Gist.

Nota: no necesitaba la devolución de llamada de cambio de altura de la solución original, por lo que falta aquí, pero puede agregarla fácilmente si es necesario.

AX
fuente
0

Si usa androidx.* clases en su proyecto, debe usar HtmlCompat.fromHtml(text, flag). La fuente del método es:

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

Es mejor manera que Html.fromHtml ya que hay menos código, solo una línea y la forma recomendada de usarlo.

oso panda
fuente
0

Puede usar una función de extensión Kotlin simple como esta:

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

Y uso:

textViewMessage.setHtmlText("Message: <b>Hello World</b>")
seyfullah.bilgin
fuente
0

Simplemente use:

String variable="StackOverflow";
textView.setText(Html.fromHtml("<b>Hello : </b>"+ variable));
Sumit Shukla
fuente