web-dev-qa-db-ja.com

XMLでhtml形式の文字列リソースからTextViewテキストを設定します

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を作成するオーバーヘッドから私を救うためにそのままにしておきたいテキストを設定します。

明らかな何かを見落としていますか?まったく不可能ですか?ヘルプや回避策を歓迎します!

編集:いくつかのことを試してみましたが、xmlのHTMLフォーマットにはいくつかの制約があるようです。

  • タグは小文字で書く必要があります

  • 言及されている一部のタグ ここ は機能しません。 <br/>(代わりに\nを使用できます)

190
slup

誰かがこれを見つけた場合に備えて、文書化されていないより良い代替手段があります(何時間も検索した後、つまずいて、最後にAndroid SDK自体のバグリストで見つけました)。 CANラップする限り、strings.xmlに生のHTMLを含めることができます

<![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)));

私見、これは動作するのに数桁優れています:-)

464
Bitbang3r

ここでの一番の答えは何か間違っていることを示唆している(または少なくとも複雑すぎる)なので、質問はかなり古いものの、これを更新する必要があると感じています。

AndroidでStringリソースを使用する場合は、JavaコードからgetString(...)を呼び出すか、レイアウトXMLでAndroid:text="@string/..."を使用するだけです。

文字列でHTMLマークアップを使用する場合でも、あまり変更する必要はありません:

Stringリソースでエスケープする必要がある文字は次のとおりです。

  • 二重引用符:"\"になります
  • 単一引用符:'\'になります
  • アンパサンド:&&#38;または&amp;になります

つまり、エスケープせずにHTMLマークアップタグを追加できます:

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

ただし、ドキュメントにリストされているとおり、<b><i>、および<u>のみを使用する必要があります。

HTML文字列from XMLを使用する場合は、Android:text="@string/..."を使用し続けるだけで問題ありません。

唯一の違いは、HTML文字列from Java codeを使用する場合は、getText(...)の代わりにgetString(...)を使用する必要があることです。前者はスタイルを保持し、後者はスタイルを削除するためです。

それと同じくらい簡単です。 CDATA、Html.fromHtml(...)はありません。

HTMLマークアップで特殊文字をdidエンコードした場合にのみHtml.fromHtml(...)が必要になります。その後、getString(...)で使用します。これは、文字列をString.format(...)に渡す場合に必要になることがあります。

これはすべて説明されています ドキュメント内 も同様です。

編集:

getText(...)とエスケープされていないHTML(私が提案したように)またはCDATAセクションとHtml.fromHtml(...)の間に違いはありません。

比較については、次の図を参照してください。

enter image description here

121
caw

HTMLタグをエスケープする...

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

Androidには、リソース文字列のタイプ(text/plainやtext/htmlなど)を示す仕様がありません。ただし、開発者がXMLファイル内でこれを指定できるようにする回避策があります。

  1. カスタム属性を定義して、Android:text属性がhtmlであることを指定します。
  2. サブクラス化されたTextViewを使用します。

これらを定義すると、setText(Html.fromHtml(...))を再度呼び出す必要なく、xmlファイルでHTMLを使用して自分自身を表現できます。このアプローチがAPIの一部ではないことにかなり驚いています。

このソリューションは、Android Studioシミュレーターがレンダリングされた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();
    }
}
}
10
Steven Spungin

最新の更新:

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));
}
9
Ranjith Kumar
  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);
3
Dishant Kawatra

サーバーから文字列HTMLを受信するときに、CDATAをxmlに入れる機会がない別のケースがあります。

サーバーから取得するものは次のとおりです。

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

}

それが役に立てば幸い!
リン

2
Linh Lino