HTML dans la ressource de chaîne?

120

Je sais que je peux mettre des balises HTML échappées dans des ressources de chaîne. Cependant, en regardant le code source de l'application Contacts, je peux voir qu'ils ont un moyen de ne pas avoir à encoder le HTML. Citation de l'application Contacts 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>

Malheureusement, lorsque j'essaye quelque chose de similaire (comme Hello, <b>World</b>!), getString()renvoie la chaîne sans les balises (je peux le voir dans logcat). Pourquoi donc? Comment puis-je obtenir la chaîne d'origine, avec les balises et tout? Comment fonctionne l'application Contacts?

Félix
la source

Réponses:

199

Vous pouvez également entourer votre html dans un CDATAbloc et getString()renvoyer votre HTML réel. Comme tel:

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

Maintenant, lorsque vous effectuez un, getString(R.string.foo)la chaîne sera HTML. Si vous avez besoin de rendre le HTML (avec le lien comme indiqué) via un clic, TextViewvous devez effectuer un Html.fromHtml(...)appel pour obtenir le texte spannable.

Donn Felker
la source
1
Non, vous devriez certainement voir la réponse de Felix. CDATA n'est pas nécessaire.
caw
4
@MarcoW. La réponse de Felix est vraie, mais l'utilisation de CDATA nous aide à ne pas nous soucier des balises html. Cette réponse doit être la bonne réponse.
slhddn
3
Si vous avez des liens dans la chaîne, n'oubliez pas d'ajouter textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs
1
J'ai dû utiliser \"pour la stylepropriété, cependant. Exemple<a style=\"...\">link</a>
Fabricio
1
CDATA vous donne beaucoup plus de flexibilité lors du style des chaînes avec des balises HTML. Je conviens que c'est la voie à suivre à 100%!
Droid Chris
89

Il semble getString()faire exactement cela - obtient une chaîne . Pour l'utiliser, vous devez utiliser getText()(et pas plus Html.fromHtml()), c'est-à-dire:

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

Cependant, il semble que la android:textpropriété fasse exactement la même chose, et ce qui suit est équivalent:

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

Et dans strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>
Félix
la source
28
Veuillez noter que seules les balises prises en charge sont <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas
2
@pawegio tu veux dire sûrement \n?
Felix
7
@Snicolas: il supporte plus que les 3 balises mentionnées dans la documentation: il supporte <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li>, <marquee>, <a>, <font> et <annotation> (voir github.com/android/platform_frameworks_base/blob/… )
rve
1
Malheureusement, en utilisant cette méthode, les variables en chaîne ne sont pas autorisées
Alessandro Muzzi
1
<font> est pris en charge sur api23, mais api10 ne l'est pas.
illusionJJ
54

La meilleure solution consiste à utiliser les ressources d'une manière:

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

et ensuite l'afficher avec:

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

Essayez d'utiliser cette ressource sans <![CDATA[ ]]>et avec tv.setText(getText(R.string.htmlsource));et vous verrez la différence.

user1006786
la source
Merci pour cette réponse, cela m'a vraiment aidé
Alsemany
Même avec un fichier HTML très volumineux et complexe?
Supuhstar
Est-ce que cela prend en charge la balise <font>?
Rohit Singh
1

Je sais que c'est une vieille question mais il semble que la réponse la plus efficace n'ait pas encore été proposée.

Utilisez simplement des HTML-escapedcaractères pour qu'il ne soit pas traité par getStringmais il sera traité par HtmlCompact.fromHtml(ou par le plus ancien Html.fromHtml).

Cela prend également en charge plus de balises comme les liens HTML, etc., pas seulement le formatage comme la getStringméthode.

Par exemple, quelque chose comme ça devrait fonctionner:

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

Dans votre cas, vous remplacez <par &lt;comme ceci:

<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
la source
0

cela fonctionne pour moi sans bloc 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`

Je l'utilise en layout.

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

Idée: mettez le HTML dans des fichiers au format JSON et stockez-les dans / res / raw. (JSON est moins pointilleux)

Stockez les enregistrements de données comme ceci dans un objet tableau:

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

Pour lire les données dans votre application:

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

Enfin, la Dataclasse n'est qu'un conteneur de variables publiques pour un accès facile ...

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;
    }
}
Quelqu'un quelque part
la source
Cela semble un peu sur-conçu, pourquoi ne pas l'enregistrer en html au lieu de json?
Misca le