HTML в строковом ресурсе?

120

Я знаю, что могу помещать экранированные HTML-теги в строковые ресурсы. Однако, глядя на исходный код приложения «Контакты», я вижу, что у них есть способ избежать кодирования HTML. Цитата из приложения "Контакты" 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>

К сожалению, когда я пробую что-то подобное (например Hello, <b>World</b>!), getString()возвращает строку без тегов (я вижу это logcat). Это почему? Как мне получить исходную строку с тегами и всем остальным? Как это делает приложение "Контакты"?

Феликс
источник

Ответы:

199

Вы также можете заключить свой html в CDATAблок и getString()вернуть ваш фактический HTML. Как такой:

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

Теперь, когда вы выполняете a, getString(R.string.foo)строка будет HTML. Если вам нужно отобразить HTML (со ссылкой, как показано) через интерактивный объект, TextViewвам нужно будет выполнить Html.fromHtml(...)вызов, чтобы получить охватываемый текст.

Донн Фелкер
источник
1
Нет, тебе обязательно стоит увидеть ответ Феликса. CDATA не нужен.
caw
4
@MarcoW. Ответ Феликса верен, но использование CDATA помогает нам не беспокоиться о тегах html. Этот ответ должен быть правильным.
slhddn
3
Если у вас есть ссылки в строке, не забудьте добавить textView.setMovementMethod (LinkMovementMethod.getInstance ());
Адарш Урс,
1
Однако мне пришлось использовать \"в качестве styleсобственности. Пример<a style=\"...\">link</a>
Fabricio
1
CDATA дает вам гораздо больше гибкости при стилизации строк с помощью тегов HTML. Я согласен, что это путь на 100%!
Droid Chris
89

Кажется getString(), именно так - получает строку . Чтобы использовать это, вы должны использовать getText()(и не более Html.fromHtml()), то есть:

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

Однако похоже, что android:textсвойство делает то же самое, и следующее эквивалентно:

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

И в strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>
Феликс
источник
28
Обратите внимание, что поддерживаются только теги <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas,
2
@pawegio, конечно, ты имеешь в виду \n?
Felix
7
@Snicolas: он поддерживает более трех тегов, упомянутых в документации: он поддерживает <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li>, <marquee>, <a>, <font> и <annotation> (см. github.com/android/platform_frameworks_base/blob/… )
rve
1
К сожалению, при использовании этого метода переменные в строке не допускаются
Алессандро Муцци,
1
<font> поддерживается api23, а api10 - нет.
иллюзияJJ
54

Лучшее решение - использовать ресурсы следующим образом:

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

а затем отобразить его с помощью:

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

Попробуйте использовать этот ресурс без <![CDATA[ ]]> и с ним, tv.setText(getText(R.string.htmlsource));и вы увидите разницу.

user1006786
источник
Спасибо за этот ответ, это действительно помогло мне
Alsemany
Даже с очень большим и сложным файлом HTML?
Supuhstar
Поддерживает ли это тег <font>?
Рохит Сингх
1

Я знаю, что это старый вопрос, но, похоже, наиболее эффективного ответа пока нет.

Просто используйте HTML-escapedсимволы, чтобы они не обрабатывались, getStringно обрабатывалисьHtmlCompact.fromHtml (или старше Html.fromHtml).

Это также поддерживает больше тегов, таких как HTML-ссылки и т. Д., А не только форматирование, например getString метод.

Например, должно работать что-то вроде этого:

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

В вашем случае вы заменить <с , &lt;как это:

<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
источник
0

у меня работает без блока 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`

Использую в верстке.

<item
    android:id="@+id/nav_premium"
    android:icon="@drawable/coins"
    android:title="@string/menu_item_purchase"
    />
Андрей Глухофф
источник
-1

Идея: поместить HTML в файлы в формате JSON и сохранить их в / res / raw. (JSON менее разборчив)

Сохраните такие записи данных в объекте массива:

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

Чтобы прочитать данные в вашем приложении:

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

Наконец, Dataкласс - это просто контейнер общедоступных переменных для легкого доступа ...

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;
    }
}
Кто-то где-то
источник
Кажется, это немного перестроено, почему бы не сохранить его в формате html вместо json?
Misca