HTML ในทรัพยากรสตริง?


120

ฉันรู้ว่าสามารถใส่แท็ก HTML ที่ใช้ Escape ในทรัพยากรสตริงได้ อย่างไรก็ตามการดูซอร์สโค้ดสำหรับแอปพลิเคชันผู้ติดต่อฉันเห็นว่าพวกเขามีวิธีที่ไม่ต้องเข้ารหัส HTML อ้างจากแอปพลิเคชันที่ติดต่อstrings.xml :

<string name="contactsSyncPlug"><font fgcolor="#ffffffff">Sync your Google contacts!</font> 
\nAfter syncing to your phone, your contacts will be available to you wherever you go.</string>

น่าเสียดายที่เมื่อฉันลองสิ่งที่คล้ายกัน (เช่นHello, <b>World</b>!) getString()ส่งคืนสตริงที่ไม่มีแท็ก (ฉันเห็นสิ่งนั้นในlogcat) ทำไมถึงเป็นเช่นนั้น? ฉันจะรับสตริงเดิมพร้อมแท็กและทุกอย่างได้อย่างไร แอปพลิเคชัน Contacts ทำงานอย่างไร?

คำตอบ:


199

คุณยังสามารถล้อมรอบ html ของคุณในCDATAบล็อกได้เช่นกันและgetString()จะส่งคืน HTML จริงของคุณ เช่นนี้:

<string name="foo"><![CDATA[Foo Bar <a href="foo?id=%s">baz</a> is cool]]></string>

ตอนนี้เมื่อคุณดำเนินgetString(R.string.foo)การสตริงจะเป็น HTML หากคุณต้องการแสดง HTML (พร้อมลิงก์ดังที่แสดง) ผ่านทางคลิกได้TextViewคุณจะต้องทำการHtml.fromHtml(...)โทรเพื่อรับข้อความที่เป็นภาษาสเปน


1
ไม่คุณควรเห็นคำตอบของเฟลิกซ์อย่างแน่นอน ไม่จำเป็นต้องใช้ CDATA
caw

4
@MarcoW คำตอบของ Felix เป็นความจริง แต่การใช้ CDATA ช่วยให้เราไม่ต้องกังวลกับแท็ก html คำตอบนี้ควรเป็นคำตอบที่ถูกต้อง
slhddn

3
หากคุณมีลิงก์ในสตริงอย่าลืมเพิ่ม textView.setMovementMethod (LinkMovementMethod.getInstance ());
Adarsh ​​Urs

1
ฉันต้องใช้\"เพื่อstyleทรัพย์สินแม้ว่า ตัวอย่าง<a style=\"...\">link</a>
Fabricio

1
CDATA ช่วยให้คุณมีความยืดหยุ่นมากขึ้นเมื่อจัดรูปแบบสตริงด้วยแท็ก HTML ฉันยอมรับว่านั่นคือหนทางที่จะไป 100%!
Droid Chris

89

ดูเหมือนว่าgetString()ไม่เพียงแค่นั้น - ได้รับสตริง ในการใช้งานคุณต้องใช้getText()(และไม่มีอีกแล้วHtml.fromHtml()) นั่นคือ:

mTextView.setText(getText(R.string.my_styled_text));

อย่างไรก็ตามดูเหมือนว่าandroid:textคุณสมบัติจะเหมือนกันและสิ่งต่อไปนี้เทียบเท่า:

<TextView android:text="@string/my_styled_text" />

และในstrings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>

28
โปรดทราบว่าแท็กที่รองรับคือ <b>, <i>, <u>: developer.android.com/guide/topics/resources/…
Snicolas

2
@pawegio แน่นอนคุณหมายถึง\n?
Felix

7
@Snicolas: รองรับแท็กมากกว่า 3 แท็กที่กล่าวถึงในเอกสาร: รองรับ <b>, <i>, <u>, <big>, <small>, <sup>, <sub>, <strike>, <li>, <marquee>, <a>, <font> และ <annotation> (ดูgithub.com/android/platform_frameworks_base/blob/… )
rve

1
โชคไม่ดีที่ใช้วิธีนี้ไม่อนุญาตให้ใช้ตัวแปรในสตริง
Alessandro Muzzi

1
<font> ได้รับการสนับสนุนที่ api23 แต่ api10 ไม่ใช่
illusionJJ

54

ทางออกที่ดีที่สุดคือการใช้ทรัพยากรในลักษณะ:

<string name="htmlsource"><![CDATA[<p>Adults are spotted gold and black on the crown, back and wings. Their face and neck are black with a white border; they have a black breast and a dark rump. The legs are black.</p><p>It is similar to two other golden plovers, Eurasian and Pacific. <h1>The American Golden Plover</h1> is smaller, slimmer and relatively longer-legged than Eurasian Golden Plover (<i>Pluvialis apricaria</i>) which also has white axillary (armpit) feathers. It is more similar to Pacific Golden Plover (<i>Pluvialis fulva</i>) with which it was once <b>considered</b> conspecific under the name \"Lesser Golden Plover\". The Pacific Golden Plover is slimmer than the American species, has a shorter primary projection, and longer legs, and is usually yellower on the back.</p><p>These birds forage for food on tundra, fields, beaches and tidal flats, usually by sight. They eat insects and crustaceans, also berries.</p>]]></string>

และแสดงด้วย:

Spanned sp = Html.fromHtml( getString(R.string.htmlsource));
tv.setText(sp);

ลองใช้ทรัพยากรนั้นโดยไม่มี<![CDATA[ ]]>และด้วยtv.setText(getText(R.string.htmlsource));แล้วคุณจะเห็นความแตกต่าง


ขอบคุณสำหรับคำตอบที่ช่วยฉันได้จริงๆ
Alsemany

แม้ว่าจะมีไฟล์ HTML ขนาดใหญ่และซับซ้อนมากก็ตาม?
Supuhstar

สิ่งนี้รองรับแท็ก <font> หรือไม่
Rohit Singh

1

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ดูเหมือนว่ายังไม่มีการเสนอคำตอบที่มีประสิทธิภาพที่สุด

เพียงแค่ใช้HTML-escapedอักขระเพื่อไม่ให้ถูกประมวลผลgetStringแต่จะถูกประมวลผลโดยHtmlCompact.fromHtml(หรือเก่ากว่าHtml.fromHtml)

นอกจากนี้ยังรองรับแท็กอื่น ๆ เช่นลิงก์ HTML เป็นต้นไม่เพียง แต่การจัดรูปแบบgetStringวิธีการ

ตัวอย่างเช่นสิ่งนี้ควรใช้งานได้:

<string name="html_message">Hello &lt;b>World&lt;/b>.</string>

val text = getString(R.string.html_message)
val result = HtmlCompact.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY)

ในกรณีของคุณคุณแทนที่<ด้วย&lt;สิ่งนี้:

<string name="contactsSyncPlug">&lt;font fgcolor="#ffffffff">Sync your Google contacts!&lt;/font> \nAfter syncing to your phone, your contacts will be available to you wherever you go.</string>

0

มันใช้งานได้สำหรับฉันโดยไม่มีบล็อก CDATA

<string name="menu_item_purchase" translatable="false"><font color="red">P</font><font color="orange">r</font><font color="yellow">e</font><font color="green">m</font><font color="white">i</font><font color="blue">u</font><font color="purple">m</font></string>`enter code here`

ฉันใช้มันในการจัดวาง

<item
    android:id="@+id/nav_premium"
    android:icon="@drawable/coins"
    android:title="@string/menu_item_purchase"
    />

-1

แนวคิด: ใส่ HTML ในไฟล์ที่จัดรูปแบบ JSON และเก็บไว้ใน / res / raw (JSON จู้จี้จุกจิกน้อยกว่า)

จัดเก็บบันทึกข้อมูลเช่นนี้ในวัตถุอาร์เรย์:

[
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    },
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    },
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    }
]

หากต้องการอ่านข้อมูลในแอปของคุณ:

private ArrayList<Data> getData(String filename) {
    ArrayList<Data> dataArray = new ArrayList<Data>();

    try {
        int id = getResources().getIdentifier(filename, "raw", getPackageName());
        InputStream input = getResources().openRawResource(id);
        int size = input.available();
        byte[] buffer = new byte[size];
        input.read(buffer);
        String text = new String(buffer);

        Gson gson = new Gson();
        Type dataType = new TypeToken<List<Map<String, Object>>>() {}.getType();
        List<Map<String, Object>> natural = gson.fromJson(text, dataType);

        // now cycle through each object and gather the data from each field
        for(Map<String, Object> json : natural) {
            final Data ad = new Data(json.get("Field1"), json.get("Field2"),  json.get("Field3"), json.get("Field4"));
            dataArray.add(ad);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    return dataArray;
}

สุดท้ายDataคลาสเป็นเพียงที่เก็บตัวแปรสาธารณะเพื่อให้เข้าถึงได้ง่าย ...

public class Data {

    public String string;
    public Integer number;
    public String somestring;
    public Integer site;
    public boolean logical;


    public Data(String string, Integer number, String somestring, boolean logical)
    {
        this.string = string;
        this.number = number;
        this.somestring = somestring;
        this.logical = logical;
    }
}

ดูเหมือนว่าจะมีการออกแบบมากเกินไปทำไมไม่บันทึกเป็น html แทน json
Misca
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.