Встановіть TextView текст з HTML-форматованого рядкового ресурсу в XML


196

У мене є кілька фіксованих рядків всередині мене strings.xml, щось на зразок:

<resources>
    <string name="somestring">
        <B>Title</B><BR/>
        Content
    </string>
</resources>

і в моєму макеті у мене є TextViewкотрий я хотів би заповнити рядком у форматі html.

<TextView android:id="@+id/formattedtext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/htmlstring"/>

якщо я це роблю, вміст - formattedtextце лише вміст somestringпозбавлених будь-яких HTML-тегів і, отже, неформатований.

Я знаю, що відформатований текст можна програмно встановити за допомогою

.setText(Html.fromHtml(somestring));

тому що я використовую це в інших частинах своєї програми, де вона працює, як очікувалося.

Для виклику цієї функції мені потрібен Activity, але на даний момент моя компонування - це просто простий більш-менш статичний вигляд у звичайному XML, і я вважаю за краще залишити його таким чином, щоб врятувати мене від накладних коштів створення Activityпросто встановити текст.

Я не помічаю щось очевидне? Це взагалі неможливо? Будь-яка допомога чи обхідні шляхи ласкаво просимо!

Редагувати: Просто спробував деякі речі, і здається, що форматування HTML у xml має деякі обмеження:

  • Теги повинні бути написані малими літерами

  • деякі згадані тут теги не працюють, наприклад <br/>( \nзамість цього можна використовувати )


1
Я вже давно знаю, але мені вдалося використовувати <br>, а не \ n для нового рядка, використовуючи html для TextView.
Там

2
Чи може це працювати лише з XML? У мене невелика щедрість на відповідь. Я б не сприймав фактичних відповідей на даний момент, які я вже закодував.
danny117

1
Мені цікаво, що ніхто не відповідав на запитання. ОП заявляє, що він знає, як це зробити зHtml (), але хоче це зробити безпосередньо у файлі макета (хоча, причини не хороші ... у вас завжди доступна активність / контекст, якщо ви малюєте на екран). Жодна з відповідей також не занурюється в ефекти якорних тегів.
lilbyrdie

Відповіді:


481

На всякий випадок, коли хтось виявить це, є краща альтернатива, яка не документально підтверджена (я зіткнувся з нею, шукаючи години, і нарешті знайшов її у списку помилок для самого Android SDK). Ви МОЖЕТЕ включати необроблений HTML у strings.xml, доки ви його не вписуєте

<![CDATA[ ...raw html... ]]>

Приклад:

<string name="nice_html">
<![CDATA[
<p>This is a html-formatted string with <b>bold</b> and <i>italic</i> text</p>
<p>This is another paragraph of the same string.</p>
]]>
</string>

Потім у своєму коді:

TextView foo = (TextView)findViewById(R.id.foo);
foo.setText(Html.fromHtml(getString(R.string.nice_html)));

ІМХО, з цим на кілька порядків приємніше працювати :-)


26
Додамо лише, що ви також можете зворотно-слідуючу апострофу / одноцитати всередині блоку CDATA, так що ви можете мати такі речі, як <b> can \ 't </b> замість нескінченно-потворного <b> can' t < / b>
Bitbang3r

5
Це все ще працює? Я просто спробував це, і він буквально відображає <p> і </p>.
Peri Hartman

1
@PeriHartman Ви також зробили Html.fromHtml(getString(R.string.nice_html))трохи? :)
async

1
Де TextView foo = (TextView) знаходитьViewById (R.id.foo); foo.setText (Html.fromHtml (getString (R.string.nice_html))); потрібно їхати?
RustyIngles

2
Чи є спосіб уникнути "Html.fromHtml"?
андроїд розробник

128

Оскільки тут головна відповідь пропонує щось не так (або, принаймні, занадто складне), я вважаю, що це слід оновити, хоча питання досить старе:

Під час використання String-ресурсів в Android, вам просто потрібно зателефонувати getString(...)з коду Java або використати android:text="@string/..."у своїй версії XML.

Навіть якщо ви хочете використовувати розмітку HTML у своїх рядках, вам не доведеться багато змінювати:

Єдині символи, які вам потрібні, щоб уникнути своїх ресурсів String:

  • подвійний лапки: "стає\"
  • єдиний лапки: 'стає\'
  • ampersand: &стає &#38;або&amp;

Це означає, що ви можете додати HTML-розмітку, не уникаючи тегів:

<string name="my_string"><b>Hello World!</b> This is an example.</string>

Однак, щоб бути впевненим, ви повинні використовувати тільки <b>, <i>і <u>як вони перераховані в документації.

Якщо ви хочете використовувати свої HTML-рядки з XML , просто продовжуйте використовувати android:text="@string/...", це буде добре.

Єдина відмінність полягає в тому, що якщо ви хочете використовувати свої HTML-рядки з коду Java , вам доведеться використовувати getText(...)замість цього getString(...)часу, оскільки перший зберігає стиль, а другий просто позбавить його.

Це так просто, як це. Ні CDATA, ні Html.fromHtml(...).

Вам потрібно буде тільки Html.fromHtml(...)якщо ви зробили закодувати свої спеціальні символи в HTML розмітці. Використовуйте його з getString(...)тоді. Це може знадобитися, якщо ви хочете передати струну String.format(...).

Це все також описано в документах .

Редагувати:

Немає різниці між getText(...)несказованим HTML (як я запропонував) або CDATAрозділами та Html.fromHtml(...).

Для порівняння див. Таку графіку:

введіть тут опис зображення


Шахта знімає його. Я використовую наступний код:getResources().getText(R.string.codename)
Si8

3
Щоб краще допомогти, мені потрібно переглянути уривки Java / XML. Але , як я вже писав: Ви тільки впевнені , що якщо ви використовуєте <b>, <i>, <u>. Інші теги не завжди підтримуються.
каре

1
Ваша відповідь працює і проста. Просто покладіть рядок у strings.xml із потрібними тегами html та відправте її з файлу xml-макета. Я використав тег <sup>.
Пері Хартман

1
Ваше - це ще одне рішення, а не альтернатива іншому, оскільки воно підтримує не всі теги, як це робить інші. Я не бачу жодної переваги в цьому рішенні, коли інше дуже просте.
mobilepotato7

1
Як у мене виникло використання "CDATA", виникла така проблема, наприклад: <! [CDATA [... HTML ...]]>, що має 22 літери, а частина html має 10. Так, якщо ви використовуєте HTML.fromhtml ( getstring (...)) ваш текст буде відображатися правильно, але для його вмісту потрібно 22 пробіли. Я використовував у перегляді списків і бачив бур'янисті простори. тож gettext () - БУЛЬШЕ.
Девід

16

Уникнути своїх тегів HTML ...

<resources>
    <string name="somestring">
        &lt;B&gt;Title&lt;/B&gt;&lt;BR/&gt;
        Content
    </string>
</resources>

Про це говорять документи: developer.android.com/intl/zh-TW/guide/topics/resources/…, але цього достатньо для того, TextViewщоб показати HTML?
Макарс

3
Я перевірив це, і якщо ви використовуєте його з вихідного коду Java, це добре. Але якщо ви асоціюєте текст безпосередньо з XML-макетом, теги відображаються у текстовому вікні (наприклад, <B> Назва </B> ...)
ZoltanF

Щоб показати текст у вікні, використовуйте клас [ developer.android.com/reference/android/text/Html.html] , зокрема fromHTML().
ekawas

@ZoltanF вірно, використовуючи android: text = "" з макета з HTML покаже теги в рядку.
Ендрю Макензі

1
Якщо ви хочете використовувати рядок HTML безпосередньо з XML, ви можете не кодувати HTML спеціальних символів у рядку. Однак, якщо ви хочете використовувати рядок з коду через, Html.fromHTML()вам потрібно кодувати спеціальні символи. Дивно!
caw

11

Для Android немає специфікації, яка б вказувала тип рядка ресурсу (наприклад, текст / звичайний текст або текст / html). Однак існує рішення, яке дозволить розробнику вказати це у файлі XML.

  1. Визначте спеціальний атрибут, щоб вказати, що атрибут text android: text - це html.
  2. Використовуйте підкласинг TextView.

Визначивши їх, ви можете виразити себе HTML в XML-файлах, не вимагаючи знову викликати setText (Html.fromHtml (...)). Я досить здивований, що такий підхід не є частиною API.

Це рішення працює настільки, що симулятор студії Android відобразить текст у вигляді HTML.

введіть тут опис зображення

res / values ​​/ strings.xml (рядовий ресурс як HTML)

<resources>
<string name="app_name">TextViewEx</string>
<string name="string_with_html"><![CDATA[
       <em>Hello</em> <strong>World</strong>!
 ]]></string>
</resources>

layout.xml (лише відповідні частини)

Оголосіть спеціальний простір імен атрибутів та додайте атрибут android_ex: isHtml. Також використовуйте підклас TextView.

<RelativeLayout
...
xmlns:android_ex="http://schemas.android.com/apk/res-auto"
...>

<tv.twelvetone.samples.textviewex.TextViewEx
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/string_with_html"
    android_ex:isHtml="true"
    />
 </RelativeLayout>

res / values ​​/ attrs.xml (визначте спеціальні атрибути для підкласу)

 <resources>
<declare-styleable name="TextViewEx">
    <attr name="isHtml" format="boolean"/>
    <attr name="android:text" />
</declare-styleable>
</resources>

TextViewEx.java (підклас TextView)

 package tv.twelvetone.samples.textviewex;

 import android.content.Context;
 import android.content.res.TypedArray;
 import android.support.annotation.Nullable;
 import android.text.Html;
 import android.util.AttributeSet;
 import android.widget.TextView;

public TextViewEx(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextViewEx, 0, 0);
    try {
        boolean isHtml = a.getBoolean(R.styleable.TextViewEx_isHtml, false);
        if (isHtml) {
            String text = a.getString(R.styleable.TextViewEx_android_text);
            if (text != null) {
                setText(Html.fromHtml(text));
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        a.recycle();
    }
}
}

Цей підхід буде кращим, якщо програма використовує рядки у форматі HTML у кількох місцях, а не викликає HTML.fromHtml у кожному місці. У самому додатку буде два перегляди: один для звичайного та один для HTML.
Манджу

10

Останнє оновлення:

Html.fromHtml(string);// застарілий після версій Android N ..

Наступний код надає підтримку версій Android N і вище ...

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
textView.setText(Html.fromHtml(yourHtmlString,Html.FROM_HTML_MODE_LEGACY));
}

else 
{
textView.setText(Html.fromHtml(yourHtmlString));
}

3
  String termsOfCondition="<font color=#cc0029>Terms of Use </font>";
  String commma="<font color=#000000>, </font>";
  String privacyPolicy="<font color=#cc0029>Privacy Policy </font>";
  Spanned text=Html.fromHtml("I am of legal age and I have read, understood, agreed and accepted the "+termsOfCondition+commma+privacyPolicy);
        secondCheckBox.setText(text);

2

У мене є ще один випадок, коли я не маю шансу ввести CDATA у xml, коли я отримую рядковий HTML від сервера.

Ось що я отримую від сервера:

<p>The quick brown&nbsp;<br />
fox jumps&nbsp;<br />
 over the lazy dog<br />
</p>

Це здається складнішим, але рішення набагато простіше.

private TextView textView;

protected void onCreate(Bundle savedInstanceState) { 
.....
textView = (TextView) findViewById(R.id.text); //need to define in your layout
String htmlFromServer = getHTMLContentFromAServer(); 
textView.setText(Html.fromHtml(htmlFromServer).toString());

}

Сподіваюся, це допомагає!
Лінх


4
де реалізація функції getHTMLContentFromAServer ()
Pallavi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.