Setel teks TextView dari sumber string berformat html dalam XML

195

Saya memiliki beberapa string tetap di dalam saya strings.xml, sesuatu seperti:

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

dan dalam tata letak saya, saya punya TextViewyang ingin saya isi dengan string berformat html.

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

jika saya melakukan ini, konten formattedtexthanya konten yang somestringdilucuti dari tag html dan dengan demikian tidak diformat.

Saya tahu bahwa adalah mungkin untuk mengatur teks yang diformat secara terprogram dengan

.setText(Html.fromHtml(somestring));

karena saya menggunakan ini di bagian lain dari program saya di mana ia berfungsi seperti yang diharapkan.

Untuk memanggil fungsi ini saya memerlukan Activity, tetapi pada saat ini tata letak saya hanya tampilan statis yang kurang lebih sederhana dalam XML polos dan saya lebih suka membiarkannya seperti itu, untuk menyelamatkan saya dari overhead pembuatan Activityhanya untuk mengatur beberapa teks.

Apakah saya mengabaikan sesuatu yang sudah jelas? Apakah itu tidak mungkin sama sekali? Selamat datang bantuan atau pemecahan masalah!

Sunting: Baru saja mencoba beberapa hal dan sepertinya format HTML di xml memiliki beberapa batasan:

  • tag harus ditulis dengan huruf kecil

  • beberapa tag yang disebutkan di sini tidak berfungsi, misalnya <br/>(dimungkinkan untuk digunakan \nsebagai gantinya)

Slup
sumber
1
Sudah lama saya tahu, tapi saya bisa menggunakan <br> dan bukan \ n untuk baris baru menggunakan html untuk TextView.
Tam
2
Bisakah ini bekerja hanya dengan xml? Saya punya hadiah kecil untuk jawabannya. Saya akan menganggap tidak sebagai jawaban faktual pada titik ini yang sudah saya kodekan di sekitarnya.
danny117
1
Saya merasa menarik bahwa tidak ada yang benar-benar menjawab pertanyaan itu. OP menyatakan bahwa dia tahu cara melakukannya dengan fromHtml (), tetapi ingin melakukannya secara langsung dalam file tata letak (walaupun, alasannya tidak baik ... Anda selalu memiliki aktivitas / konteks yang tersedia jika Anda menggambar di layar). Tidak satu pun dari jawaban yang menyelami efek dari anchor tag, baik.
lilbyrdie

Jawaban:

481

Kalau-kalau ada yang menemukan ini, ada alternatif yang lebih baik yang tidak didokumentasikan (saya tersandung setelah mencari berjam-jam, dan akhirnya menemukannya di daftar bug untuk Android SDK itu sendiri). Anda BISA menyertakan HTML mentah di strings.xml, selama Anda membungkusnya

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

Contoh:

<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>

Kemudian, dalam kode Anda:

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

IMHO, ini beberapa urutan besarnya lebih baik untuk bekerja dengan :-)

Bitbang3r
sumber
26
Hanya untuk menambahkan, Anda juga dapat melakukan backslash-escape apostrophes / single-quotes di dalam blok CDATA, sehingga Anda dapat memiliki hal-hal seperti <b> tidak dapat </b> alih-alih <b> tidak dapat menjadi lebih buruk seperti sebelumnya & dapat <apos; t < / b>
Bitbang3r
5
Apakah ini masih berfungsi? Saya baru saja mencobanya dan secara harfiah menampilkan <p> dan </p>.
Peri Hartman
1
@PeriHartman Apakah Anda juga melakukan Html.fromHtml(getString(R.string.nice_html))sedikit? :)
async
1
Di mana TextView foo = (TextView) findViewById (R.id.foo); foo.setText (Html.fromHtml (getString (R.string.nice_html))); harus pergi?
RustyIngles
2
Apakah ada cara untuk menghindari "Html.fromHtml"?
pengembang android
127

Karena jawaban teratas di sini adalah menyarankan sesuatu yang salah (atau setidaknya terlalu rumit), saya merasa ini harus diperbarui, walaupun pertanyaannya sudah cukup lama:

Saat menggunakan sumber daya String di Android, Anda hanya perlu menelepon getString(...)dari kode Java atau menggunakan android:text="@string/..."XML layout Anda.

Bahkan jika Anda ingin menggunakan markup HTML di Strings Anda, Anda tidak perlu banyak berubah:

Satu-satunya karakter yang Anda butuhkan untuk melarikan diri dalam sumber daya String Anda adalah:

  • tanda kutip ganda: "menjadi\"
  • tanda kutip tunggal: 'menjadi\'
  • ampersand: &menjadi &#38;atau&amp;

Itu berarti Anda dapat menambahkan markup HTML Anda tanpa keluar dari tag:

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

Namun, yang pasti, Anda hanya boleh menggunakan <b>, <i>dan <u>seperti yang tercantum dalam dokumentasi.

Jika Anda ingin menggunakan string HTML Anda dari XML , teruslah menggunakannya android:text="@string/...", itu akan berfungsi dengan baik.

Satu-satunya perbedaan adalah bahwa, jika Anda ingin menggunakan string HTML Anda dari kode Java , Anda harus menggunakan getText(...)bukan getString(...)sekarang, karena yang pertama mempertahankan gaya dan yang terakhir hanya akan menghapusnya.

Semudah itu. Tidak ada CDATA, tidak Html.fromHtml(...).

Anda hanya akan perlu Html.fromHtml(...)jika Anda melakukan encode karakter khusus Anda di HTML markup. Gunakan dengan getString(...)itu. Ini bisa diperlukan jika Anda ingin meneruskan String String.format(...).

Ini semua dijelaskan dalam dokumen juga.

Edit:

Tidak ada perbedaan antara getText(...)dengan HTML yang tidak terhapus (seperti yang saya usulkan) atau CDATAbagian dan Html.fromHtml(...).

Lihat gambar berikut untuk perbandingan:

masukkan deskripsi gambar di sini

gak
sumber
Milik saya menanggalkannya. Saya menggunakan kode berikut:getResources().getText(R.string.codename)
Si8
3
Untuk membantu lebih baik, saya perlu melihat kutipan Java / XML. Tapi seperti yang saya sudah menulis: Anda hanya yakin jika Anda menggunakan <b>, <i>, <u>. Tag lain tidak selalu didukung.
gak
1
Jawaban Anda berhasil dan sederhana. Masukkan saja string Anda ke strings.xml, dengan tag html yang diinginkan, dan rujuk dari file layout xml Anda. Saya menggunakan tag <sup>.
Peri Hartman
1
Milik Anda adalah solusi lain, bukan alternatif bagi yang lain karena tidak mendukung semua tag, seperti yang lainnya. Saya gagal melihat keuntungan dalam solusi ini ketika yang lain sangat sederhana.
mobilepotato7
1
Seperti yang saya alami menggunakan "CDATA" memiliki masalah, sesuatu seperti ini misalnya: <! [CDATA [... HTML ...]]> yang memiliki 22 huruf dan bagian html memiliki 10. jadi jika Anda menggunakan HTML.fromhtml ( getstring (...)) teks Anda akan ditampilkan dengan benar tetapi konten teks membutuhkan 22 spasi. Saya digunakan dalam listview dan melihat ruang kurus. jadi gettext () adalah LEBIH BAIK.
David
16

Lepaskan tag HTML Anda ...

<resources>
    <string name="somestring">
        &lt;B&gt;Title&lt;/B&gt;&lt;BR/&gt;
        Content
    </string>
</resources>
ekawas
sumber
Itulah yang dikatakan dokumen: developer.android.com/intl/zh-TW/guide/topics/resources/… tetapi apakah itu cukup untuk TextViewmenampilkan HTML?
Macarse
3
Saya telah menguji ini, dan jika Anda menggunakannya dari kode sumber java, tidak apa-apa. Tetapi jika Anda mengaitkan teks Anda langsung dari tata letak XML, tag ditampilkan pada tampilan teks (mis. <B> Judul </B> ...)
ZoltanF
Untuk menampilkan teks dalam tampilan, gunakan kelas [ developer.android.com/reference/android/text/Html.html] , khususnya fromHTML().
ekawas
@ZoltanF benar, menggunakan android: text = "" dari tata letak dengan HTML akan menampilkan tag dalam string.
Andrew Mackenzie
1
Jika Anda ingin menggunakan string HTML langsung dari XML, Anda tidak boleh menyandikan karakter khusus HTML dalam string. Namun, jika Anda ingin menggunakan string dari kode melalui Html.fromHTML()Anda harus menyandikan karakter khusus. Aneh!
gak
11

Android tidak memiliki spesifikasi untuk menunjukkan jenis string sumber daya (mis. Teks / polos atau teks / html). Ada solusi, namun, yang akan memungkinkan pengembang untuk menentukan ini dalam file XML.

  1. Tetapkan atribut khusus untuk menentukan bahwa atribut android: text adalah html.
  2. Gunakan TextView subkelas.

Setelah Anda menentukan ini, Anda dapat mengekspresikan diri dengan HTML dalam file xml tanpa harus memanggil setText (Html.fromHtml (...)) lagi. Saya agak terkejut bahwa pendekatan ini bukan bagian dari API.

Solusi ini berfungsi sampai-sampai simulator Android studio akan menampilkan teks sebagai HTML yang dirender.

masukkan deskripsi gambar di sini

res / values ​​/ strings.xml (sumber string sebagai HTML)

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

layout.xml (hanya bagian yang relevan)

Nyatakan namespace atribut khusus, dan tambahkan atribut android_ex: isHtml. Juga gunakan subkelas dari 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 (tentukan atribut khusus untuk subkelas)

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

TextViewEx.java (subclass dari 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();
    }
}
}
Steven Spungin
sumber
Pendekatan ini akan lebih baik, Jika aplikasi menggunakan string berformat HTML di beberapa tempat, alih-alih memanggil HTML.fromHtml setiap tempat. Aplikasi itu sendiri akan memiliki dua tampilan satu untuk normal dan satu untuk HTML.
Manju
10

Pembaruan terbaru:

Html.fromHtml(string);// dihentikan setelah versi Android N ..

Kode berikut memberikan dukungan untuk Android N dan versi di atas ...

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));
}
Ranjith Kumar
sumber
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);
Piring Kawatra
sumber
2

Saya memiliki kasus lain ketika saya tidak memiliki kesempatan untuk memasukkan CDATA ke xml karena saya menerima string HTML dari server.

Inilah yang saya dapatkan dari server:

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

Tampaknya lebih rumit tetapi solusinya jauh lebih sederhana.

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

}

Semoga ini bisa membantu!
Linh

Linh Lino
sumber
4
di mana penerapan fungsi getHTMLContentFromAServer ()
Pallavi