HTML en el recurso de cadena?

120

Sé que puedo poner etiquetas HTML de escape en recursos de cadena. Sin embargo, al mirar el código fuente de la aplicación Contactos puedo ver que tienen una forma de no tener que codificar el HTML. Cita de la aplicación Contactos strings.xml :

<string name="contactsSyncPlug"><font fgcolor="#ffffffff">Sync your Google contacts!</font> 
\nAfter syncing to your phone, your contacts will be available to you wherever you go.</string>

Desafortunadamente, cuando intento algo similar (como Hello, <b>World</b>!), getString()devuelve la cadena sin las etiquetas (puedo ver eso logcat). ¿Porqué es eso? ¿Cómo puedo obtener la cadena original, con etiquetas y todo? ¿Cómo lo hace la aplicación Contactos?

Felix
fuente

Respuestas:

199

También puede rodear su html en un CDATAbloque y getString()devolverá su HTML real. Como tal:

<string name="foo"><![CDATA[Foo Bar <a href="foo?id=%s">baz</a> is cool]]></string>

Ahora, cuando realice una, getString(R.string.foo)la cadena será HTML. Si necesita renderizar el HTML (con el enlace como se muestra) a través de un clic TextView, deberá realizar una Html.fromHtml(...)llamada para obtener el texto expandible.

Donn Felker
fuente
1
No, definitivamente deberías ver la respuesta de Felix. CDATA no es necesario.
caw
4
@MarcoW. La respuesta de Felix es cierta, pero el uso de CDATA nos ayuda a no preocuparnos por las etiquetas html. Esta respuesta debe ser la respuesta correcta.
slhddn
3
Si tiene enlaces en la cadena, no olvide agregar textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs
1
Sin embargo, tuve que usarlo \"como stylepropiedad. Ejemplo<a style=\"...\">link</a>
Fabricio
1
CDATA le brinda mucha más flexibilidad al diseñar cadenas con etiquetas HTML. ¡Estoy de acuerdo en que es el camino a seguir al 100%!
Droid Chris
89

Parece que getString()hace precisamente eso: obtiene una cuerda . Para usar esto, debe usar getText()(y no más Html.fromHtml()), es decir:

mTextView.setText(getText(R.string.my_styled_text));

Sin embargo, parece que la android:textpropiedad hace exactamente lo mismo, y lo siguiente es equivalente:

<TextView android:text="@string/my_styled_text" />

Y en strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>
Felix
fuente
28
Tenga en cuenta que solo las etiquetas admitidas son <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas
2
@pawegio seguramente te refieres \n?
Felix
7
@Snicolas: admite más de las 3 etiquetas mencionadas en la documentación: admite <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li>, <marquee>, <a>, <font> y <annotation> (consulte github.com/android/platform_frameworks_base/blob/… )
rve
1
Desafortunadamente, al usar este método, no se permiten variables en la cadena
Alessandro Muzzi
1
<font> es compatible con api23, pero api10 no.
illusionJJ
54

La mejor solución es utilizar los recursos de una manera:

<string name="htmlsource"><![CDATA[<p>Adults are spotted gold and black on the crown, back and wings. Their face and neck are black with a white border; they have a black breast and a dark rump. The legs are black.</p><p>It is similar to two other golden plovers, Eurasian and Pacific. <h1>The American Golden Plover</h1> is smaller, slimmer and relatively longer-legged than Eurasian Golden Plover (<i>Pluvialis apricaria</i>) which also has white axillary (armpit) feathers. It is more similar to Pacific Golden Plover (<i>Pluvialis fulva</i>) with which it was once <b>considered</b> conspecific under the name \"Lesser Golden Plover\". The Pacific Golden Plover is slimmer than the American species, has a shorter primary projection, and longer legs, and is usually yellower on the back.</p><p>These birds forage for food on tundra, fields, beaches and tidal flats, usually by sight. They eat insects and crustaceans, also berries.</p>]]></string>

y luego mostrarlo con:

Spanned sp = Html.fromHtml( getString(R.string.htmlsource));
tv.setText(sp);

Intente utilizar ese recurso sin <![CDATA[ ]]>y con tv.setText(getText(R.string.htmlsource));y verá la diferencia.

usuario1006786
fuente
Gracias por esta respuesta, esto realmente me ayudó
Alsemany
¿Incluso con un archivo HTML muy grande y complejo?
Supuhstar
¿Es compatible con la etiqueta <font>?
Rohit Singh
1

Sé que esta es una pregunta antigua, pero parece que aún no se ha propuesto la respuesta más eficiente.

Simplemente use HTML-escapedcaracteres para que no sea procesado por getStringpero será procesado por HtmlCompact.fromHtml(o el más antiguo Html.fromHtml).

Esto también admite más etiquetas como enlaces HTML, etc., no solo formatear como getStringmétodo.

Por ejemplo, algo como esto debería funcionar:

<string name="html_message">Hello &lt;b>World&lt;/b>.</string>

val text = getString(R.string.html_message)
val result = HtmlCompact.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY)

En su caso, lo reemplaza <con algo &lt;así:

<string name="contactsSyncPlug">&lt;font fgcolor="#ffffffff">Sync your Google contacts!&lt;/font> \nAfter syncing to your phone, your contacts will be available to you wherever you go.</string>
bio007
fuente
0

funciona para mí sin el bloque CDATA.

<string name="menu_item_purchase" translatable="false"><font color="red">P</font><font color="orange">r</font><font color="yellow">e</font><font color="green">m</font><font color="white">i</font><font color="blue">u</font><font color="purple">m</font></string>`enter code here`

Lo uso en diseño.

<item
    android:id="@+id/nav_premium"
    android:icon="@drawable/coins"
    android:title="@string/menu_item_purchase"
    />
Andrew Glukhoff
fuente
-1

Idea: ponga el HTML en archivos con formato JSON y guárdelos en / res / raw. (JSON es menos exigente)

Almacene los registros de datos como este en un objeto de matriz:

[
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    },
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    },
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    }
]

Para leer los datos en su aplicación:

private ArrayList<Data> getData(String filename) {
    ArrayList<Data> dataArray = new ArrayList<Data>();

    try {
        int id = getResources().getIdentifier(filename, "raw", getPackageName());
        InputStream input = getResources().openRawResource(id);
        int size = input.available();
        byte[] buffer = new byte[size];
        input.read(buffer);
        String text = new String(buffer);

        Gson gson = new Gson();
        Type dataType = new TypeToken<List<Map<String, Object>>>() {}.getType();
        List<Map<String, Object>> natural = gson.fromJson(text, dataType);

        // now cycle through each object and gather the data from each field
        for(Map<String, Object> json : natural) {
            final Data ad = new Data(json.get("Field1"), json.get("Field2"),  json.get("Field3"), json.get("Field4"));
            dataArray.add(ad);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    return dataArray;
}

Finalmente, la Dataclase es solo un contenedor de variables públicas para un fácil acceso ...

public class Data {

    public String string;
    public Integer number;
    public String somestring;
    public Integer site;
    public boolean logical;


    public Data(String string, Integer number, String somestring, boolean logical)
    {
        this.string = string;
        this.number = number;
        this.somestring = somestring;
        this.logical = logical;
    }
}
Alguien en algún lugar
fuente
Parece un poco sobrecargado, ¿por qué no guardarlo en html en lugar de json?
Misca