Задать текст TextView из строкового ресурса в формате html в XML - PullRequest
191 голосов
/ 13 июля 2010

У меня есть несколько фиксированных строк внутри 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)

Ответы [ 7 ]

466 голосов
/ 28 мая 2011

На всякий случай, если кто-нибудь найдет это, есть более приятная альтернатива, которая не документирована (я споткнулся о нее после нескольких часов поиска и, наконец, нашел ее в списке ошибок для самого 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)));

ИМХО, на несколько порядков лучше работать с: -)

121 голосов
/ 13 августа 2013

Поскольку верхний ответ здесь предполагает что-то неправильное (или, по крайней мере, слишком сложное), я чувствую, что это следует обновить, хотя вопрос довольно старый:

При использовании ресурсов String в Android вам просто нужно вызвать getString(...) из кода Java или использовать android:text="@string/..." в XML-коде макета.

Даже если вы хотите использовать разметку HTML в своих строках, вам не нужно много менять:

Единственные символы, которые вам нужно экранировать в ресурсах String:

  • двойная кавычка: " становится \"
  • одиночная кавычка: ' становится \'
  • амперсанд: & становится &#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(...).

Все это также описано в документации .

Edit:

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

См. Следующий график для сравнения:

enter image description here

15 голосов
/ 13 июля 2010

Побег ваши HTML-теги ...

<resources>
    <string name="somestring">
        &lt;B&gt;Title&lt;/B&gt;&lt;BR/&gt;
        Content
    </string>
</resources>
10 голосов
/ 22 ноября 2016

Последнее обновление:

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));
}
10 голосов
/ 22 сентября 2016

Android не имеет спецификации для указания типа строки ресурса (например, text / plain или text / html).Однако существует обходной путь, который позволит разработчику указать это в файле XML.

  1. Определите пользовательский атрибут, чтобы указать, что атрибут android: text имеет значение html.
  2. Используйте подклассифицированное TextView.

Как только вы определите их, вы можете выразить себя с помощью HTML в файлах XML без необходимости повторного вызова setText (Html.fromHtml (...)).Я довольно удивлен, что этот подход не является частью API.

Это решение работает до такой степени, что симулятор студии Android будет отображать текст в виде визуализированного HTML.

enter image description here

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();
    }
}
}
3 голосов
/ 24 января 2019
  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 голосов
/ 11 марта 2014

У меня есть еще один случай, когда у меня нет шансов вставить 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());

}

Надеюсь, это поможет!
Лин

...