HTML no recurso de string?

120

Eu sei que posso colocar tags HTML de escape em recursos de string. No entanto, olhando o código-fonte do aplicativo de contatos, posso ver que eles têm uma maneira de não ter que codificar o HTML. Citação do aplicativo de contatos 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>

Infelizmente, quando tento algo semelhante (como Hello, <b>World</b>!), getString()retorna a string sem as tags (posso ver isso em logcat). Por que é que? Como posso obter a string original, com tags e tudo? Como o aplicativo de contatos está fazendo isso?

Felix
fonte

Respostas:

199

Você também pode envolver seu html em um CDATAbloco e getString()retornará seu HTML real. Assim:

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

Agora, quando você executa um, getString(R.string.foo)a string será HTML. Se você precisar renderizar o HTML (com o link conforme mostrado) por meio de um clicável, TextViewserá necessário realizar uma Html.fromHtml(...)chamada para obter o texto gerável.

Donn Felker
fonte
1
Não, você definitivamente deveria ver a resposta de Felix. CDATA não é necessário.
caw
4
@MarcoW. A resposta de Felix é verdadeira, mas usar CDATA nos ajuda a não nos preocuparmos com tags html. Esta resposta deve ser a resposta correta.
slhddn de
3
Se você tiver links na string, não se esqueça de adicionar textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs
1
Eu tive que usar \"como stylepropriedade, no entanto. Exemplo<a style=\"...\">link</a>
Fabricio
1
O CDATA oferece muito mais flexibilidade ao estilizar strings com tags HTML. Eu concordaria que esse é o caminho a percorrer 100%!
Droid Chris de
89

Parece que getString()faz exatamente isso - recebe uma string . Para usar isso, você deve usar getText()(e não mais Html.fromHtml()), ou seja:

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

No entanto, parece que a android:textpropriedade faz exatamente a mesma coisa, e o seguinte é equivalente:

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

E em strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>
Felix
fonte
28
Observe que somente as tags compatíveis são <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas
2
@pawegio com certeza você quer dizer \n?
Felix
7
@Snicolas: suporta mais do que as 3 tags mencionadas na documentação: suporta <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li>, <marquee>, <a>, <font> e <annotation> (consulte github.com/android/platform_frameworks_base/blob/… )
rve
1
Infelizmente, usando este método, variáveis ​​em string não são permitidas
Alessandro Muzzi
1
<font> é compatível com api23, mas api10 não.
illusionJJ
54

A melhor solução é usar os recursos de uma forma:

<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 então exibi-lo com:

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

Tente usar esse recurso sem <![CDATA[ ]]>e com tv.setText(getText(R.string.htmlsource));e você verá a diferença.

user1006786
fonte
Obrigado por esta resposta, isso realmente me ajudou
Alsemany
Mesmo com um arquivo HTML muito grande e complexo?
Supuhstar
Isso é compatível com a tag <font>?
Rohit Singh
1

Eu sei que esta é uma pergunta antiga, mas parece que a resposta mais eficiente ainda não foi proposta.

Apenas use HTML-escapedcaracteres para que não seja processado por, getStringmas será processado por HtmlCompact.fromHtml(ou o mais antigo Html.fromHtml).

Isso também suporta mais tags, como links HTML, etc., não apenas formatação como getStringmétodo.

Por exemplo, algo assim deve 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)

No seu caso, você substitui <por &lt;assim:

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

funciona para mim sem o bloco 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`

Eu uso isso no layout.

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

Idéia: coloque o HTML em arquivos formatados em JSON e armazene-os em / res / raw. (JSON é menos exigente)

Armazene os registros de dados como este em um 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 ler os dados em seu aplicativo:

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, a Dataclasse é apenas um contêiner de variáveis ​​públicas para fácil acesso ...

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;
    }
}
Alguém algum lugar
fonte
Parece um pouco exagerado, por que não salvá-lo em html em vez de json?
Misca