HTML w zasobie ciągu?

120

Wiem, że mogę umieścić znaczniki HTML ze ucieczką w zasobach ciągów. Jednak patrząc na kod źródłowy aplikacji Kontakty, widzę, że nie muszą one kodować kodu HTML. Cytat z aplikacji Kontakty 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>

Niestety, gdy próbuję czegoś podobnego (podobnego Hello, <b>World</b>!), getString()zwraca ciąg bez tagów (widzę to w logcat). Dlaczego? Jak mogę uzyskać oryginalny ciąg z tagami i wszystkim? Jak działa aplikacja Kontakty?

Felix
źródło

Odpowiedzi:

199

Możesz również otoczyć swój kod HTML CDATAblokiem, co getString()spowoduje zwrócenie rzeczywistego kodu HTML. Jak takie:

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

Teraz, gdy wykonasz getString(R.string.foo)ciąg, będzie to HTML. Jeśli chcesz wyrenderować kod HTML (z linkiem, jak pokazano) za pomocą elementu klikalnego TextView, musisz wykonać Html.fromHtml(...)wywołanie, aby uzyskać tekst, który można przesuwać.

Donn Felker
źródło
1
Nie, zdecydowanie powinieneś zobaczyć odpowiedź Felixa. CDATA nie jest konieczne.
krakanie
4
@MarcoW. Odpowiedź Felixa jest prawdziwa, ale użycie CDATA pomaga nam nie martwić się o tagi HTML. Ta odpowiedź powinna być poprawna.
slhddn
3
Jeśli masz linki w ciągu, nie zapomnij dodać textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs
1
Musiałem jednak użyć \"na stylewłasność. Przykład<a style=\"...\">link</a>
Fabricio
1
CDATA zapewnia znacznie większą elastyczność podczas stylizowania ciągów za pomocą tagów HTML. Zgadzam się, że jest to droga na 100%!
Droid Chris
89

Wydaje się, getString()że właśnie to - dostaje ciąg . Aby z tego skorzystać, musisz użyć getText()(i nie więcej Html.fromHtml()), tj .:

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

Jednak wydaje się, że android:textwłaściwość robi to samo, a następujące są równoważne:

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

A w strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>
Felix
źródło
28
Pamiętaj, że tylko obsługiwane tagi to <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas,
2
@pawegio na pewno masz na myśli \n?
Felix
7
@Snicolas: obsługuje więcej niż 3 tagi wymienione w dokumentacji: obsługuje <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li> <marquee>, a, <font> i <adnotacja> (patrz github.com/android/platform_frameworks_base/blob/... )
Rve
1
Niestety, używając tej metody, zmienne w ciągu znaków nie są dozwolone
Alessandro Muzzi
1
<font> jest obsługiwany w api23, ale api10 nie.
iluzja
54

Najlepszym rozwiązaniem jest takie wykorzystanie zasobów:

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

a następnie wyświetlić go za pomocą:

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

Spróbuj użyć tego zasobu bez <![CDATA[ ]]>iz, tv.setText(getText(R.string.htmlsource));a zobaczysz różnicę.

user1006786
źródło
Dziękuję za tę odpowiedź, która naprawdę mi pomogła
Alsemany
Nawet z bardzo dużym i złożonym plikiem HTML?
Supuhstar
Czy to obsługuje tag <font>?
Rohit Singh
1

Wiem, że to stare pytanie, ale wydaje się, że nie zaproponowano jeszcze najbardziej skutecznej odpowiedzi.

Po prostu użyj HTML-escapedznaków, aby nie został przetworzony przez, getStringale zostanie przetworzony przez HtmlCompact.fromHtml(lub starszego Html.fromHtml).

Obsługuje to również więcej tagów, takich jak linki HTML itp., Nie tylko formatowanie, jak getStringmetoda.

Na przykład coś takiego powinno działać:

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

W twoim przypadku wymiany <z &lt;tak:

<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
źródło
0

działa u mnie bez bloku 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`

Używam go w układzie.

<item
    android:id="@+id/nav_premium"
    android:icon="@drawable/coins"
    android:title="@string/menu_item_purchase"
    />
Andrew Glukhoff
źródło
-1

Pomysł: umieść HTML w plikach w formacie JSON i zapisz je w / res / raw. (JSON jest mniej wybredny)

Przechowuj rekordy danych w następujący sposób w obiekcie tablicy:

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

Aby odczytać dane w swojej aplikacji:

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

Wreszcie Dataklasa jest po prostu kontenerem zmiennych publicznych dla łatwego dostępu ...

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;
    }
}
Ktoś gdzieś
źródło
Wydaje się, że jest trochę przesadzony, dlaczego nie zapisać go w formacie HTML zamiast JSON?
Misca