HTML nella risorsa stringa?


120

So di poter inserire tag HTML con escape nelle risorse stringa. Tuttavia, guardando il codice sorgente dell'applicazione Contatti, posso vedere che hanno un modo per non dover codificare l'HTML. Citazione dall'applicazione Contatti 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>

Sfortunatamente, quando provo qualcosa di simile (come Hello, <b>World</b>!), getString()restituisce la stringa senza i tag (posso vederlo in logcat). Perché? Come posso ottenere la stringa originale, con i tag e tutto il resto? Come funziona l'applicazione Contatti?

Risposte:


199

Puoi anche racchiudere il tuo html in un CDATAblocco e getString()restituirà il tuo vero HTML. Come tale:

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

Ora, quando esegui una, getString(R.string.foo)la stringa sarà HTML. Se è necessario eseguire il rendering dell'HTML (con il collegamento come mostrato) tramite un clic, TextViewè necessario eseguire una Html.fromHtml(...)chiamata per ottenere il testo spannabile.


1
No, dovresti assolutamente vedere la risposta di Felix. CDATA non è necessario.
caw

4
@MarcoW. La risposta di Felix è vera ma l'utilizzo di CDATA ci aiuta a non preoccuparci dei tag html. Questa risposta dovrebbe essere la risposta corretta.
slhddn

3
Se hai collegamenti nella stringa, non dimenticare di aggiungere textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs,

1
Ho dovuto usare \"per la styleproprietà, però. Esempio<a style=\"...\">link</a>
Fabricio

1
CDATA offre molta più flessibilità durante lo styling delle stringhe con tag HTML. Sono d'accordo che è la strada da percorrere al 100%!
Droid Chris

89

Sembra che getString()faccia proprio questo: ottiene una stringa . Per usarlo, devi usare getText()(e non di più Html.fromHtml()), cioè:

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

Tuttavia, sembra che la android:textproprietà faccia la stessa cosa e quanto segue è equivalente:

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

E in strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>

28
Tieni presente che solo i tag supportati sono <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas

2
@pawegio sicuramente intendi \n?
Felix,

7
@Snicolas: supporta più dei 3 tag menzionati nella documentazione: supporta <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li>, <marquee>, <a>, <font> e <annotation> (vedi github.com/android/platform_frameworks_base/blob/... )
RVE

1
Sfortunatamente utilizzando questo metodo, le variabili in stringa non sono consentite
Alessandro Muzzi

1
<font> è supportato in api23, ma api10 non lo è.
illusionJJ

54

La soluzione migliore è utilizzare le risorse in un modo:

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

e poi visualizzarlo con:

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

Prova a usare quella risorsa senza <![CDATA[ ]]>e con tv.setText(getText(R.string.htmlsource));e vedrai la differenza.


Grazie per questa risposta, questo mi ha davvero aiutato
Alsemany

Anche con un file HTML molto grande e complesso?
Supuhstar

Questo supporta il tag <font>?
Rohit Singh

1

So che questa è una vecchia domanda, ma sembra che la risposta più efficace non sia stata ancora proposta.

Usa solo i HTML-escapedcaratteri in modo che non venga elaborato da, getStringma verrà elaborato da HtmlCompact.fromHtml(o dal vecchio Html.fromHtml).

Questo supporta anche più tag come link HTML ecc., Non solo formattazione come getStringmetodo.

Ad esempio qualcosa del genere dovrebbe funzionare:

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

Nel tuo caso sostituisci <con &lt;questo:

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

0

funziona per me senza blocco 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 nel layout.

<item
    android:id="@+id/nav_premium"
    android:icon="@drawable/coins"
    android:title="@string/menu_item_purchase"
    />

-1

Idea: inserisci l'HTML in file formattati JSON e memorizzali in / res / raw. (JSON è meno esigente)

Memorizza i record di dati in questo modo in un oggetto array:

[
    {
        "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
    }
]

Per leggere i dati nella tua app:

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

Infine, la Dataclasse è solo un contenitore di variabili pubbliche per un facile accesso ...

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

Sembra un po 'troppo ingegnerizzato, perché non salvarlo in html invece che in json?
Misca
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.