Установить TextView текст из HTML-форматированного строкового ресурса в XML

у меня есть некоторые фиксированные строки внутри моего 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 просто для набора текста.

я упускаю что-то очевидное? Неужели это вообще невозможно? Любая помощь или обходные пути приветствуются!

Edit: просто попробовал некоторые вещи, и это кажется, что форматирование HTML в xml имеет некоторые ограничения:

  • теги должны быть написаны в нижнем регистре

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

6 ответов


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

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


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

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

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

единственные символы, которые вам нужно escape в ваших строковых ресурсах:

  • двойные кавычки: " становится \"
  • одинарные кавычки: ' становится \'
  • амперсанд: & становится &#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(...) если ты ... --60-->сделал кодируйте свои специальные символы в разметке HTML. Используйте его с getString(...) затем. Это может быть необходимо, если вы хотите передать строку String.format(...).

это все описано в документах как хорошо.

Edit:

нет никакой разницы между getText(...) С unescaped HTML (как я предложил) или CDATA разделы и Html.fromHtml(...).

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

enter image description here


побег HTML-тегов ...

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

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

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

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

это решение работает в той степени, что Android studio simulator будет отображать текст в формате HTML.

enter image description here

res / значения / строки.xml (строковый ресурс как HTML)

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

макет.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-код.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));
}

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

}

надеюсь, что это помогает!
Линх