ตั้งค่า 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
Tam

2
สามารถทำงานได้จากเพียงแค่ XML ฉันมีคำตอบเล็ก ๆ น้อย ๆ ฉันจะไม่ตอบคำถามตามความเป็นจริง ณ จุดนี้ฉันได้เขียนไปแล้ว
danny117

1
ฉันพบว่ามันน่าสนใจที่ไม่มีใครตอบคำถามจริง สถานะ OP เขารู้วิธีใช้ด้วย fromHtml () แต่ต้องการทำโดยตรงในไฟล์เลย์เอาต์ (แม้ว่าเหตุผลไม่ดี ... คุณมีกิจกรรม / บริบทพร้อมเสมอถ้าคุณวาด หน้าจอ). ไม่มีคำตอบใดที่ดำดิ่งลงสู่เอฟเฟกต์ของแท็กจุดยึดเช่นกัน
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)));

IMHO นี่เป็นคำสั่งที่หลากหลายสำหรับการทำงานกับ :-)


26
เพียงเพิ่มคุณยังสามารถ backslash-escape apostrophes / อัญประกาศเดี่ยวภายในบล็อก CDATA ดังนั้นคุณสามารถมีสิ่งต่าง ๆ เช่น <b> ไม่สามารถ </b> แทนที่จะเป็น infinitely-uglier <b> can & apos; t < / b>
Bitbang3r

5
ยังใช้งานได้หรือไม่ ฉันลองแล้วมันจะแสดง <p> และ </p> อย่างแท้จริง
Peri Hartman

1
@PeriHartman คุณยังทำHtml.fromHtml(getString(R.string.nice_html))บิตหรือไม่ :)
async

1
TextView foo = (TextView) findViewById (R.id.foo) อยู่ที่ไหน; foo.setText (Html.fromHtml (getString (R.string.nice_html))); ต้องการจะไป?
RustyIngles

2
มีวิธีหลีกเลี่ยง "Html.fromHtml" หรือไม่
นักพัฒนา android

128

เนื่องจากคำตอบยอดนิยมที่นี่เป็นการแนะนำสิ่งที่ผิด (หรืออย่างน้อยก็ซับซ้อนเกินไป) ฉันรู้สึกว่าควรอัปเดตแม้ว่าคำถามจะค่อนข้างเก่า:

เมื่อใช้ทรัพยากร 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(...)นี้อาจจะจำเป็นถ้าคุณต้องการที่จะผ่านสตริง

นี่คือทั้งหมดที่อธิบายไว้ในเอกสารเช่นกัน

แก้ไข:

มีความแตกต่างระหว่างไม่เป็นgetText(...)กับไม่ใช้ Escape HTML (ที่ผมได้เสนอชื่อ) หรือส่วนและCDATAHtml.fromHtml(...)

ดูภาพกราฟิกต่อไปนี้สำหรับการเปรียบเทียบ:

ป้อนคำอธิบายรูปภาพที่นี่


ฉันกำลังลอกมันออก ฉันใช้รหัสต่อไปนี้:getResources().getText(R.string.codename)
Si8

3
เพื่อช่วยให้ดีขึ้นฉันต้องดูข้อความที่ตัดตอนมาจาก Java / XML แต่ในฐานะที่ผมเคยเขียน: คุณเป็นเพียงแน่ใจว่าถ้าคุณกำลังใช้<b>, ,<i> <u>แท็กอื่น ๆ ไม่ได้รับการสนับสนุนเสมอไป
caw

1
คำตอบของคุณใช้ได้ง่ายและเรียบง่าย เพียงแค่ใส่สตริงของคุณใน strings.xml ด้วยแท็ก html ที่ต้องการและอ้างอิงจากไฟล์ xml เลย์เอาต์ของคุณ ฉันใช้แท็ก <sup>
Peri Hartman

1
ของคุณเป็นโซลูชันอื่นไม่ใช่ทางเลือกอื่นเนื่องจากไม่รองรับแท็กทั้งหมดเช่นอื่น ฉันไม่เห็นความได้เปรียบใด ๆ ในการแก้ปัญหานี้เมื่ออื่น ๆ นั้นง่ายมาก
mobilepotato7

1
ในขณะที่ฉันพบปัญหาการใช้ "CDATA" มีปัญหาบางอย่างเช่นนี้: <! [CDATA [... HTML ... ]]>> ที่มี 22 ตัวอักษรและส่วน html มี 10 ดังนั้นถ้าคุณใช้ HTML.fromhtml ( getstring (... )) ข้อความของคุณจะแสดงอย่างถูกต้อง แต่เนื้อหาของข้อความต้องมีช่องว่าง 22 ตัวอักษร ฉันใช้ในรายการมุมมองและเห็นช่องว่างที่อ่อนแอ ดังนั้น gettext () จึงดีกว่า
David

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 หรือไม่
Macarse

3
ฉันได้ทำการทดสอบแล้วและถ้าคุณใช้จากซอร์สโค้ดจาวาก็ใช้ได้ แต่ถ้าคุณเชื่อมโยงข้อความของคุณโดยตรงจากโครงร่าง XML แท็กจะแสดงในมุมมองข้อความ (เช่น <B> ชื่อ </B> ... )
ZoltanF

ในการแสดงข้อความในมุมมองที่ใช้ในชั้นเรียน [ developer.android.com/reference/android/text/Html.html]fromHTML()โดยเฉพาะ
ekawas

@ZoltanF ถูกต้องโดยใช้ android: text = "" จากเลย์เอาต์ที่มี HTML จะแสดงแท็กในสตริง
Andrew Mackenzie

1
หากคุณต้องการใช้สตริง HTML โดยตรงจาก XML คุณไม่สามารถเข้ารหัสอักขระพิเศษ HTML ในสตริงได้ อย่างไรก็ตามหากคุณต้องการใช้สตริงจากรหัสผ่านHtml.fromHTML()คุณจะต้องเข้ารหัสตัวอักษรพิเศษ แปลก!
กา

11

Android ไม่มีข้อมูลจำเพาะเพื่อระบุประเภทของสตริงทรัพยากร (เช่น text / plain หรือ text / html) อย่างไรก็ตามมีวิธีแก้ไขปัญหาที่จะช่วยให้นักพัฒนาซอฟต์แวร์สามารถระบุได้ในไฟล์ XML

  1. กำหนดแอตทริบิวต์ที่กำหนดเองเพื่อระบุว่า android: text attribute คือ html
  2. ใช้ TextView แบบ subclassed

เมื่อคุณกำหนดสิ่งเหล่านี้คุณสามารถแสดงตัวเองด้วย 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 (เฉพาะส่วนที่เกี่ยวข้องเท่านั้น)

ประกาศ namespace ของแอตทริบิวต์ที่กำหนดเองและเพิ่มคุณสมบัติ 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
Manju

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

}

หวังว่ามันจะช่วย!
Linh


4
โดยที่การใช้งานของ getHTMLContentFromAServer () ฟังก์ชั่น
Pallavi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.