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>

Тепер при виконанні getString(R.string.foo)рядка буде HTML. Якщо вам потрібно надати HTML (із посиланням, як показано) за допомогою кнопки, натиснувши кнопку, TextViewвам потрібно буде здійснити Html.fromHtml(...)дзвінок, щоб отримати текст, що перекладається.


1
Ні, ви обов'язково повинні побачити відповідь Фелікса. CDATA не потрібен.
каре

4
@MarcoW. Відповідь Фелікса правдива, але використання CDATA допомагає нам не турбуватися про теги html. Ця відповідь повинна бути правильною відповіддю.
slhddn

3
Якщо у вас є посилання в рядку, не забудьте додати textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs

1
Я повинен був використовувати \"для styleвласності, хоча. Приклад<a style=\"...\">link</a>
Fabricio

1
CDATA надає набагато більше гнучкості під час стилізації рядків з тегами HTML. Я погодився б, що це шлях на 100%!
Дроїд Кріс

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?
Фелікс

7
@Snicolas: він підтримує більше, ніж 3 теги, згадані в документації: він підтримує <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 - ні.
illusionJJ

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));і ви побачите різницю.


Дякую за цю відповідь, це мені справді допомогло
Алсемані

Навіть з дуже великим і складним HTML-файлом?
Супухстар

Чи підтримує цей тег <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>

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?
Міска
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.