Establecer TextView texto del recurso de cadena con formato html en XML


Tengo algunas cadenas fijas dentro de mi strings.xml, algo así como:

<resources>
    <string name="somestring">
        <B>Title</B><BR/>
        Content
    </string>
</resources>

Y en mi diseño tengo un TextView que me gustaría rellenar con la cadena con formato html.

<TextView android:id="@+id/formattedtext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/htmlstring"/>

Si hago esto, el contenido de formattedtext es solo el contenido de somestring despojado de cualquier etiqueta html y, por lo tanto, sin formato.

Sé que es posible establecer el texto formateado mediante programación con

.setText(Html.fromHtml(somestring));

Porque uso esto en otras partes de mi programa donde está trabajando como se esperaba.

Para llamar a esta función necesito un Activity, pero por el momento mi diseño es solo una simple vista más o menos estática en XML plano y preferiría dejarlo de esa manera, para salvarme de la sobrecarga de crear un Activity solo para establecer un texto.

¿Estoy pasando por alto algo obvio? No es posible en absoluto? Cualquier ayuda o soluciones bienvenidas!

Editar: Acabo de probar algunas cosas y parece que el formato HTML en xml tiene algunas restricciones:

  • Las etiquetas deben escribirse en minúsculas

  • Algunas etiquetas que se mencionan aquí no funcionan, por ejemplo <br/> (es posible usar \n en su lugar)

Author: Community, 2010-07-13

6 answers

En caso de que alguien encuentre esto, hay una mejor alternativa que no está documentada (me tropecé con ella después de buscar durante horas, y finalmente lo encontré en la lista de errores para el propio SDK de Android). Tú CAN incluir HTML sin procesar en cadenas.xml, siempre y cuando lo envuelva en

<![CDATA[ ...raw html... ]]>

Ejemplo:

<string name="nice_html">
<![CDATA[
<p>This is a html-formatted string with <b>bold</b> and <i>italic</i> text</p>
<p>This is another paragraph of the same string.</p>
]]>
</string>

Entonces, en su código:

TextView foo = (TextView)findViewById(R.id.foo);
foo.setText(Html.fromHtml(getString(R.string.nice_html)));

EN mi humilde opinión, esto es varios órdenes de magnitud más agradable para trabajar con: -)

 451
Author: Bitbang3r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-28 03:52:44

Como la respuesta principal aquí es sugerir algo incorrecto (o al menos demasiado complicado), creo que esto debe actualizarse, aunque la pregunta es bastante antigua:

Al usar recursos de cadena en Android, solo tienes que llamar a getString(...) desde código Java o usar android:text="@string/..." en tu XML de diseño.

Incluso si desea usar marcado HTML en sus cadenas, no tiene que cambiar mucho:

Los únicos caracteres que necesita para escapar en sus recursos de cadena son:

  • comillas dobles: " se convierte en \"
  • comillas simples: ' se convierte en \'
  • ampersand: & se convierte en &#38; o &amp;

Eso significa que puede agregar su marcado HTML sin escapar las etiquetas:

<string name="my_string"><b>Hello World!</b> This is an example.</string>

Sin embargo, para estar seguro, solo debe usar <b>, <i> y <u> como se enumeran en la documentación.

Si quieres usar tus cadenas HTML desde XML , sigue usando android:text="@string/...", funcionará bien.

La única diferencia es que, si quieres usar tus cadenas HTML desde código Java, tienes que usar getText(...) en lugar de getString(...) ahora, ya que el primero mantiene el estilo y el segundo simplemente lo quitará.

Es tan fácil como eso. No CDATA, no Html.fromHtml(...).

Solo necesitará Html.fromHtml(...) si codificó sus caracteres especiales en el marcado HTML. Utilícelo con getString(...) entonces. Esto puede ser necesario si desea pasar la cadena a String.format(...).

Todo esto también se describe en los documentos.

Editar:

No hay diferencia entre getText(...) con HTML no guardado (como he propuesto) o CDATA secciones y Html.fromHtml(...).

Vea el siguiente gráfico para una comparación:

introduzca la descripción de la imagen aquí

 113
Author: caw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-01 10:48:26

Escape sus etiquetas HTML ...

<resources>
    <string name="somestring">
        &lt;B&gt;Title&lt;/B&gt;&lt;BR/&gt;
        Content
    </string>
</resources>
 15
Author: ekawas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-13 13:07:08

Android no tiene una especificación para indicar el tipo de cadena de recurso (por ejemplo, texto/plano o texto/html). Sin embargo, hay una solución alternativa que permitirá al desarrollador especificar esto dentro del archivo XML.

  1. Defina un atributo personalizado para especificar que el atributo android:text es html.
  2. Utilice una subclase TextView.

Una vez que defina estos, puede expresarse con HTML en archivos xml sin tener que llamar a setText(Html.fromHtml(...)) nuevo. Estoy bastante sorprendido de que este enfoque no sea parte de la API.

Esta solución funciona en la medida en que el simulador de Android Studio muestre el texto como HTML renderizado.

introduzca la descripción de la imagen aquí

Res/values/strings.xml (el recurso de cadena como HTML)

<resources>
<string name="app_name">TextViewEx</string>
<string name="string_with_html"><![CDATA[
       <em>Hello</em> <strong>World</strong>!
 ]]></string>
</resources>

Diseño.xml (solo las partes relevantes)

Declare el espacio de nombres del atributo personalizado y agregue el atributo android_ex:isHtml. También utilice la subclase de TextView.

<RelativeLayout
...
xmlns:android_ex="http://schemas.android.com/apk/res-auto"
...>

<tv.twelvetone.samples.textviewex.TextViewEx
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/string_with_html"
    android_ex:isHtml="true"
    />
 </RelativeLayout>

Res/values/attrs.xml (definir los atributos personalizados para la subclase)

 <resources>
<declare-styleable name="TextViewEx">
    <attr name="isHtml" format="boolean"/>
    <attr name="android:text" />
</declare-styleable>
</resources>

TextViewEx.java (la subclase de TextView)

 package tv.twelvetone.samples.textviewex;

 import android.content.Context;
 import android.content.res.TypedArray;
 import android.support.annotation.Nullable;
 import android.text.Html;
 import android.util.AttributeSet;
 import android.widget.TextView;

public TextViewEx(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextViewEx, 0, 0);
    try {
        boolean isHtml = a.getBoolean(R.styleable.TextViewEx_isHtml, false);
        if (isHtml) {
            String text = a.getString(R.styleable.TextViewEx_android_text);
            if (text != null) {
                setText(Html.fromHtml(text));
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        a.recycle();
    }
}
}
 7
Author: Steven Spungin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-22 04:16:14

Última actualización:

Html.fromHtml (string); / / obsoleto después de las versiones de Android N..

El siguiente código da soporte a Android N y versiones anteriores...

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
textView.setText(Html.fromHtml(yourHtmlString,Html.FROM_HTML_MODE_LEGACY));
}

else 
{
textView.setText(Html.fromHtml(yourHtmlString));
}
 7
Author: Ranjith Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-22 14:51:10

Tengo otro caso cuando no tengo oportunidad de poner CDATA en el xml ya que recibo la cadena HTML de un servidor.

Esto es lo que obtengo de un servidor:

<p>The quick brown&nbsp;<br />
fox jumps&nbsp;<br />
 over the lazy dog<br />
</p>

Parece ser más complicado, pero la solución es mucho más simple.

private TextView textView;

protected void onCreate(Bundle savedInstanceState) { 
.....
textView = (TextView) findViewById(R.id.text); //need to define in your layout
String htmlFromServer = getHTMLContentFromAServer(); 
textView.setText(Html.fromHtml(htmlFromServer).toString());

}

Espero que ayude!
Linh

 2
Author: Linh Lino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-24 02:50:54