แหล่งข้อมูลเกี่ยวกับสตริง

ทรัพยากรสตริงมีสตริงข้อความสำหรับแอปพลิเคชันของคุณ พร้อมด้วยการจัดรูปแบบและการจัดรูปแบบข้อความที่ไม่บังคับ มีทรัพยากร 3 ประเภทที่สามารถให้ แอปพลิเคชันของคุณด้วยสตริง:

String
ทรัพยากร XML ที่มีสตริงเดียว
อาร์เรย์สตริง
ทรัพยากร XML ที่มีอาร์เรย์ของสตริง
สตริงจำนวน (พหูพจน์)
ทรัพยากร XML ที่มีสตริงต่างๆ สำหรับรูปพหูพจน์

สตริงทั้งหมดสามารถใช้มาร์กอัปการจัดรูปแบบและอาร์กิวเมนต์การจัดรูปแบบบางอย่าง สำหรับ ข้อมูลเกี่ยวกับการจัดรูปแบบและการจัดรูปแบบสตริง โปรดดูที่ส่วนเกี่ยวกับการจัดรูปแบบและการจัดรูปแบบ

สตริง

สตริงเดียวที่สามารถอ้างอิงจากแอปพลิเคชันหรือจากไฟล์แหล่งข้อมูลอื่นๆ (เช่น เป็นเลย์เอาต์ XML)

หมายเหตุ: สตริงเป็นแหล่งข้อมูลพื้นฐานที่ใช้อ้างอิง โดยใช้ค่าที่ระบุในแอตทริบิวต์ name (ไม่ใช่ชื่อไฟล์ XML) คุณจึงสามารถ รวมทรัพยากรสตริงกับทรัพยากรพื้นฐานอื่นๆ ไว้ในไฟล์ XML เดียว ภายใต้องค์ประกอบ <resources> 1 รายการ

ตำแหน่งที่ตั้งไฟล์:

res/values/filename.xml
ตั้งชื่อไฟล์ตามใจชอบ name ขององค์ประกอบ <string> จะใช้เป็น รหัสทรัพยากร
ประเภทข้อมูลทรัพยากรที่คอมไพล์:
ตัวชี้แหล่งข้อมูลไปยัง String
การอ้างอิงทรัพยากร:
ใน Java: R.string.string_name
ใน XML:@string/string_name
ไวยากรณ์:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
องค์ประกอบ:
<resources>
ต้องระบุ ต้องเป็นโหนดรูท

ไม่มีแอตทริบิวต์

<string>
สตริงที่อาจมีแท็กการจัดรูปแบบ ระวังว่าคุณต้องหลีกเลี่ยงเครื่องหมายอะพอสทรอฟีและ เครื่องหมายอัญประกาศ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีจัดรูปแบบและจัดรูปแบบสตริงอย่างถูกต้อง โปรดดูที่การจัดรูปแบบและการจัดรูปแบบด้านล่าง

ดังนี้

name
สตริง ชื่อของสตริง ชื่อนี้จะใช้เป็นทรัพยากร ID
ตัวอย่าง:
ไฟล์ XML ที่บันทึกไว้ที่ res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

XML เค้าโครงนี้จะใช้สตริงกับมุมมอง:

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" />

โค้ดของแอปพลิเคชันนี้จะเรียกสตริง:

Kotlin

val string: String = getString(R.string.hello)

Java

String string = getString(R.string.hello);

คุณจะใช้ getString(int) หรือ getText(int) เพื่อเรียกดูสตริง getText(int) จะเก็บการจัดรูปแบบ Rich Text ใดๆ ที่ใช้กับสตริง

อาร์เรย์สตริง

อาร์เรย์ของสตริงที่อ้างอิงจากแอปพลิเคชันได้

หมายเหตุ: อาร์เรย์สตริงเป็นทรัพยากรที่เรียบง่ายที่ใช้อ้างอิง โดยใช้ค่าที่ระบุในแอตทริบิวต์ name (ไม่ใช่ชื่อไฟล์ XML) อาส คุณสามารถรวมทรัพยากรอาร์เรย์สตริงกับทรัพยากรง่ายๆ อื่นๆ ในไฟล์ XML เดียว ภายใต้องค์ประกอบ <resources> 1 รายการ

ตำแหน่งที่ตั้งไฟล์:

res/values/filename.xml
ตั้งชื่อไฟล์ตามใจชอบ name ขององค์ประกอบ <string-array> จะใช้เป็น รหัสทรัพยากร
ประเภทข้อมูลทรัพยากรที่คอมไพล์:
ตัวชี้ทรัพยากรไปยังอาร์เรย์ของ String
การอ้างอิงทรัพยากร:
ใน Java: R.array.string_array_name
ใน XML: @[package:]array/string_array_name
ไวยากรณ์:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
        name="string_array_name">
        <item
            >text_string</item>
    </string-array>
</resources>
องค์ประกอบ:
<resources>
ต้องระบุ ต้องเป็นโหนดรูท

ไม่มีแอตทริบิวต์

<string-array>
กำหนดอาร์เรย์ของสตริง มีองค์ประกอบ <item> อย่างน้อย 1 รายการ

ดังนี้

name
สตริง ชื่อของอาร์เรย์ ชื่อนี้จะใช้เป็นทรัพยากร รหัสที่ใช้อ้างอิงอาร์เรย์
<item>
สตริงที่อาจมีแท็กการจัดรูปแบบ ค่าสามารถเป็นการอ้างอิงไปยังค่าอื่น ของทรัพยากรสตริง ต้องเป็นองค์ประกอบย่อยขององค์ประกอบ <string-array> โปรดระวัง ต้องหลีกเครื่องหมายอะพอสทรอฟี เครื่องหมายอัญประกาศ ดูการจัดรูปแบบและการจัดรูปแบบด้านล่างสำหรับ ข้อมูลเกี่ยวกับการจัดสไตล์และจัดรูปแบบสตริงอย่างเหมาะสม

ไม่มีแอตทริบิวต์

ตัวอย่าง:
ไฟล์ XML ที่บันทึกไว้ที่ res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="planets_array">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
        <item>Mars</item>
    </string-array>
</resources>

โค้ดของแอปพลิเคชันนี้จะดึงอาร์เรย์สตริง

Kotlin

val array: Array<String> = resources.getStringArray(R.array.planets_array)

Java

Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);

สตริงจำนวน (พหูพจน์)

ภาษาแต่ละภาษามีกฎที่แตกต่างกันสำหรับข้อตกลงด้านไวยากรณ์และปริมาณ เป็นภาษาอังกฤษ เช่น จำนวน 1 เป็นกรณีพิเศษ เราเขียนเป็น "หนังสือ 1 เล่ม" แต่สำหรับจำนวนอื่นๆ เราจะ เขียนว่า "n หนังสือ" ความแตกต่างระหว่างเอกพจน์และพหูพจน์นี้พบได้ทั่วไป แต่ ภาษาสร้างความแตกต่างได้ชัดเจนขึ้น ชุดอุปกรณ์ทั้งหมดที่ Android รองรับคือ zero one, two, few, many และ other

กฎในการตัดสินว่าจะใช้กรณีใดกับภาษาและจำนวนนั้นอาจมีความซับซ้อนมาก Android จึงมีวิธีการต่างๆ เช่น getQuantityString()เพื่อเลือก แหล่งข้อมูลที่เหมาะสมสำหรับคุณ

แม้ว่าก่อนหน้านี้จะเรียกว่า "สตริงจำนวน" (และยังคงเรียกสิ่งนี้ใน API) ปริมาณ สตริงควรใช้สำหรับรูปพหูพจน์เท่านั้น การใช้สตริงจำนวนเพื่อ นำบางอย่าง เช่น "กล่องจดหมาย" ของ Gmail เทียบกับ "กล่องจดหมาย (12)" เมื่อมีข้อความที่ยังไม่อ่าน การใช้สตริงจำนวนแทนคำสั่ง if อาจจะดูสะดวก แต่โปรดทราบว่าบางภาษา (เช่น จีน) ไม่ต้องใช้ไวยากรณ์ ความแตกต่างเลย ดังนั้นคุณจะได้รับสตริง other เสมอ

การเลือกสตริงที่จะใช้จะขึ้นอยู่กับความจำเป็นด้านไวยากรณ์เท่านั้น ในภาษาอังกฤษ ระบบจะละเว้นสตริงสำหรับ zero แม้ว่าจำนวนจะเป็น 0 เนื่องจาก 0 ไม่มีความผิดทางไวยากรณ์จาก 2 หรือหมายเลขอื่นๆ ยกเว้น 1 ("ศูนย์หนังสือ", "หนังสือหนึ่งเล่ม" "หนังสือ 2 เล่ม" เป็นต้น) ในทางกลับกัน ในภาษาเกาหลีเฉพาะสตริง other คือ ที่เคยใช้

อย่าหลงผิดนะเพราะว่า two อาจหมายถึง จำนวน 2: ภาษาอาจกำหนดให้ 2, 12, 102 (เป็นต้น) ต้องพิจารณาเหมือนกับ แต่ต่างกันกับจำนวนอื่น อาศัยนักแปลของคุณเพื่อให้ทราบว่าความแตกต่างใด เป็นภาษาของพวกเขาจริงๆ

ถ้าข้อความของคุณไม่มีตัวเลขปริมาณ อาจไม่เหมาะกับ พหูพจน์ ตัวอย่างเช่น ในลิทัวเนีย รูปเอกพจน์ใช้สำหรับทั้ง 1 และ 101 ดังนั้น "1 หนังสือ" เท่ากับ แปลว่า "1 knyga" และ "101 books" แปลว่า "101 knyga" ขณะเดียวกัน "หนังสือ" คือ "knyga" และ "หลายเล่ม" คือ "daug knygปิดการใช้งาน" หากข้อความพหูพจน์ภาษาอังกฤษมีคำว่า "a book" (เอกพจน์) และ "หนังสือหลายเล่ม" (พหูพจน์) ไม่มี ตัวเลขจริง อาจแปลว่า "knyga" (หนังสือ)/"daug knygปิดการใช้งาน" (หลายเล่ม) แต่มี กฎของลิทัวเนียจะแสดงคำว่า "knyga" (หนังสือเล่มเดียว) เมื่อหมายเลขเป็น 101

คุณหลีกเลี่ยงสตริงจำนวนได้โดยใช้สูตรที่มีค่าเป็นกลางของจำนวน เช่น "หนังสือ: 1" ซึ่งทำให้ชีวิตของคุณและนักแปล ใช้ได้ง่ายขึ้น หากเป็นรูปแบบที่ยอมรับได้สำหรับแอปพลิเคชันของคุณ

ใน API 24 ขึ้นไป คุณสามารถใช้ ICU ที่มีประสิทธิภาพมากขึ้นได้ MessageFormat แทน

หมายเหตุ: คอลเล็กชันรูปพหูพจน์เป็นแหล่งข้อมูลที่เรียบง่ายที่ อ้างอิงโดยใช้ค่าที่ระบุในแอตทริบิวต์ name (ไม่ใช่ชื่อของ XML ) ดังนั้น คุณจะสามารถรวมทรัพยากรพหูพจน์กับแหล่งข้อมูลง่ายๆ อื่นๆ ใน ไฟล์ XML ภายใต้องค์ประกอบ <resources> 1 รายการ

ตำแหน่งที่ตั้งไฟล์:

res/values/filename.xml
ตั้งชื่อไฟล์ตามใจชอบ name ขององค์ประกอบ <plurals> จะใช้เป็น รหัสทรัพยากร
การอ้างอิงทรัพยากร:
ใน Java: R.plurals.plural_name
ไวยากรณ์:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals
        name="plural_name">
        <item
            quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
            >text_string</item>
    </plurals>
</resources>
องค์ประกอบ:
<resources>
ต้องระบุ ต้องเป็นโหนดรูท

ไม่มีแอตทริบิวต์

<plurals>
คอลเล็กชันสตริงซึ่งมีสตริง 1 สตริงโดยขึ้นอยู่กับจำนวนของ บางสิ่ง มีองค์ประกอบ <item> อย่างน้อย 1 รายการ

ดังนี้

name
สตริง ชื่อของสตริงคู่นั้น ชื่อนี้จะใช้เป็น รหัสทรัพยากร
<item>
สตริงพหูพจน์หรือเอกพจน์ ค่าสามารถเป็นการอ้างอิงไปยังค่าอื่น ของทรัพยากรสตริง ต้องเป็นองค์ประกอบย่อยขององค์ประกอบ <plurals> โปรดระวังว่าคุณจะต้อง ยกเว้นเครื่องหมายอะพอสทรอฟีและเครื่องหมายคำพูด ดูการจัดรูปแบบและ การจัดรูปแบบด้านล่างเพื่อดูข้อมูลเกี่ยวกับการจัดรูปแบบและจัดรูปแบบสตริงอย่างถูกต้อง

ดังนี้

quantity
คีย์เวิร์ด ค่าที่ระบุว่าควรใช้สตริงนี้เมื่อใด ถูกต้อง พร้อมตัวอย่างโดยสังเขปในวงเล็บ ได้แก่
ค่าคำอธิบาย
zeroเมื่อภาษากำหนดให้ใช้ตัวเลข 0 เป็นกรณีพิเศษ (เช่น ในภาษาอาหรับ)
oneเมื่อภาษากำหนดให้ใช้ตัวเลข 1 ตัวเป็นพิเศษ (เช่น หมายเลข 1 ในภาษาอังกฤษและภาษาอื่นๆ ส่วนใหญ่ ส่วนในภาษารัสเซีย ตัวเลขใดก็ตามที่ลงท้ายด้วย 1 แต่ไม่ได้ลงท้ายด้วย 11 จะอยู่ในคลาสนี้)
twoเมื่อภาษากำหนดให้ใช้ตัวเลข 2 ตัวเป็นพิเศษ (เช่น 2 ตัวเลขในภาษาเวลส์ หรือ 102 ในภาษาสโลวีเนีย)
fewเมื่อภาษากำหนดให้ปฏิบัติต่อ "เล็ก" เป็นพิเศษ ตัวเลข (เช่น 2, 3 และ 4 ในภาษาเช็ก หรือตัวเลขที่ลงท้ายด้วย 2, 3 หรือ 4 แต่ไม่ใช่ 12, 13 หรือ 14 ในภาษาโปแลนด์)
manyเมื่อภาษากำหนดให้ใช้ "ขนาดใหญ่" เป็นพิเศษ (เช่นเบอร์ที่ลงท้ายด้วย 11-99 ในภาษามอลตา)
otherเมื่อภาษาไม่ได้กำหนดให้มีการจัดการเป็นพิเศษกับจำนวนที่ระบุ (เช่น ตัวเลขทั้งหมดเป็นภาษาจีน หรือ 42 ในภาษาอังกฤษ)
ตัวอย่าง:
ไฟล์ XML ที่บันทึกไว้ที่ res/values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="numberOfSongsAvailable">
        <!--
             As a developer, you should always supply "one" and "other"
             strings. Your translators will know which strings are actually
             needed for their language. Always include %d in "one" because
             translators will need to use %d for languages where "one"
             doesn't mean 1 (as explained above).
          -->
        <item quantity="one">%d song found.</item>
        <item quantity="other">%d songs found.</item>
    </plurals>
</resources>

ไฟล์ XML ที่บันทึกไว้ที่ res/values-pl/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="numberOfSongsAvailable">
        <item quantity="one">Znaleziono %d piosenkę.</item>
        <item quantity="few">Znaleziono %d piosenki.</item>
        <item quantity="other">Znaleziono %d piosenek.</item>
    </plurals>
</resources>

การใช้งาน:

Kotlin

val count = getNumberOfSongsAvailable()
val songsFound = resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count)

Java

int count = getNumberOfSongsAvailable();
Resources res = getResources();
String songsFound = res.getQuantityString(R.plurals.numberOfSongsAvailable, count, count);

เมื่อใช้เมธอด getQuantityString() คุณจะต้องส่ง count 2 ครั้งหากสตริงมี การจัดรูปแบบสตริงด้วยตัวเลข ตัวอย่างเช่น สำหรับสตริง %d songs found พารามิเตอร์ count รายการแรกจะเลือกสตริงพหูพจน์ที่เหมาะสม และ พารามิเตอร์ count รายการที่ 2 จะแทรกลงในตัวยึดตำแหน่ง %d ถ้าพหูพจน์ของคุณ สตริงจะไม่มีการจัดรูปแบบสตริง คุณไม่จำเป็นต้องส่งพารามิเตอร์ที่ 3 ไปยัง getQuantityString

รูปแบบและสไตล์

เรื่องสําคัญบางประการที่คุณควรทราบเกี่ยวกับวิธี จัดรูปแบบและจัดรูปแบบทรัพยากรสตริง

จัดการสัญลักษณ์พิเศษ

เมื่อสตริงมีอักขระที่มีการใช้งานพิเศษใน XML คุณต้องไม่ใช้อักขระหลีก ตามกฎการ Escape ของ XML/HTML มาตรฐาน หากต้องการยกเว้นอักขระหลีก ที่มีความหมายพิเศษใน Android คุณควรใช้แบ็กสแลชไว้ด้านหน้า

โดยค่าเริ่มต้น Android จะยุบลำดับอักขระช่องว่างให้เป็นช่องว่างเดียว คุณหลีกเลี่ยงปัญหานี้ได้ด้วยการใส่เครื่องหมายคำพูดคู่ล้อมรอบส่วนที่เกี่ยวข้องในสตริง ในกรณีนี้ อักขระช่องว่างทั้งหมด (รวมถึงบรรทัดใหม่) จะยังคงอยู่ภายในภูมิภาคที่ยกข้อความมา เครื่องหมายอัญประกาศคู่จะช่วยให้คุณสามารถใช้เครื่องหมายคำพูดแบบเดี่ยวที่ไม่เป็นอักขระหลีกตามปกติได้เช่นกัน

อักขระ แบบฟอร์มที่กำหนดเป็นอักขระหลีก
@ \@
? \?
บรรทัดใหม่ \n
Tab \t
อักขระ Unicode ของ U+XXXX \uXXXX
เครื่องหมายคำพูดเดี่ยว (')

รายการใดรายการหนึ่งต่อไปนี้

  • \'
  • ใส่เครื่องหมายอัญประกาศคู่ล้อมรอบสตริงทั้งหมด (เช่น "This'll work")
เครื่องหมายคำพูดคู่ (") \"

โปรดทราบว่าการล้อมรอบสตริงที่มีเครื่องหมายคำพูดเดี่ยวไม่ทำงาน

การยุบช่องว่างและการ Escape ของ Android เกิดขึ้นหลังจากที่ ไฟล์ทรัพยากรได้รับการแยกวิเคราะห์เป็น XML ซึ่งหมายความว่า <string> &#32; &#8200; &#8195;</string> (เว้นวรรค, การเว้นวรรค, เว้นวรรค Unicode Em) ทั้งหมดยุบให้เหลือเพียงช่องเดียว (" ") เนื่องจากเป็นช่องว่าง Unicode ทั้งหมดหลังจากที่แยกวิเคราะห์ไฟล์เป็น XML หากต้องการรักษาการเว้นวรรคไว้ตามเดิม คุณสามารถใส่เครื่องหมายคำพูดทั้ง 2 ชุด (<string>" &#32; &#8200; &#8195;"</string>) หรือใช้ Android Escape (<string> \u0032 \u8200 \u8195</string>)

หมายเหตุ: จากมุมมองของโปรแกรมแยกวิเคราะห์ XML ไม่มีความแตกต่างระหว่าง <string>"Test this"</string> และ <string>&quot;Test this&quot;</string> เลย ทั้ง 2 รูปแบบ จะไม่แสดงเครื่องหมายคำพูดใดๆ แต่จะเรียกใช้เครื่องหมายคำพูดที่รักษาช่องว่างของ Android (ซึ่งจะไม่มี ที่นำไปใช้ได้จริงในกรณีนี้)

การจัดรูปแบบสตริง

ถ้าต้องการจัดรูปแบบสตริง ก็ทำได้โดยใส่อาร์กิวเมนต์รูปแบบในแหล่งข้อมูลสตริง ดังที่แสดงในแหล่งข้อมูลตัวอย่างต่อไปนี้

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

ในตัวอย่างนี้ สตริงรูปแบบมีอาร์กิวเมนต์ 2 ตัว ได้แก่ %1$s เป็นสตริง และ %2$d เป็นเลขทศนิยม จากนั้นจัดรูปแบบสตริงโดยเรียกใช้ getString(int, Object...) เช่น

Kotlin

var text = getString(R.string.welcome_messages, username, mailCount)

Java

String text = getString(R.string.welcome_messages, username, mailCount);

การจัดรูปแบบด้วยมาร์กอัป HTML

คุณเพิ่มการจัดรูปแบบให้กับสตริงได้ด้วยมาร์กอัป HTML เช่น

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="welcome">Welcome to <b>Android</b>!</string>
</resources>

องค์ประกอบ HTML ต่อไปนี้ได้รับการสนับสนุน

  • ตัวหนา: <b>
  • ตัวเอียง: <i>, <reference>, <dfn>, <em>
  • ข้อความขนาดใหญ่ขึ้น 25%: <big>
  • ข้อความขนาดเล็กลง 20%: <ขนาดเล็ก>
  • การตั้งค่าคุณสมบัติของแบบอักษร: <font face=”font_family“ color=”hex_color”> ตัวอย่างของ ชุดแบบอักษรที่เป็นไปได้ ได้แก่ monospace, serif และ sans_serif
  • การตั้งค่าชุดแบบอักษรที่มีความกว้างอักษรขนาดเดียว: <tt>
  • ขีดทับ: <s>, <strike>, <del>
  • ขีดเส้นใต้: <u>
  • ตัวยก: <sup>
  • ตัวห้อย: <sub>
  • หัวข้อย่อย: <ul>, <li>
  • ตัวแบ่งบรรทัด: <br>
  • แผนก: <div>
  • รูปแบบ CSS: <span style=”color|background_color|text-decoration”>
  • ย่อหน้า: <p dir=”rtl | ltr” style=”...”>

หากไม่ได้ใช้การจัดรูปแบบ คุณก็ตั้งค่าข้อความ TextView ได้โดยตรงโดยการเรียกใช้ setText(java.lang.CharSequence) แต่ในบางกรณีคุณอาจ ต้องการสร้างทรัพยากรข้อความที่มีการจัดรูปแบบซึ่งใช้เป็นสตริงรูปแบบด้วย โดยปกติ ไม่ทำงานเนื่องจาก format(String, Object...) และ getString(int, Object...) วิธีตัดรูปแบบทั้งหมด จากสตริง ในการแก้ปัญหานี้ ให้เขียนแท็ก HTML โดยใช้อักขระหลีก เอนทิตี ซึ่งจะมีการกู้คืนด้วย fromHtml(String) หลังจากทำการจัดรูปแบบแล้ว เช่น

  1. จัดเก็บทรัพยากรข้อความที่จัดรูปแบบเป็นสตริงที่ใช้ HTML เป็นอักขระหลีก ดังนี้
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    เพิ่มองค์ประกอบ <b> ในสตริงที่จัดรูปแบบนี้ โปรดสังเกตว่าวงเล็บเปิดคือ ซ่อน HTML โดยใช้รูปแบบ &lt;

  2. จากนั้นจัดรูปแบบสตริงตามปกติ แต่ให้เรียกใช้ fromHtml(String) เพื่อ แปลงข้อความ HTML ให้เป็นข้อความที่จัดรูปแบบ

    Kotlin

    val text: String = getString(R.string.welcome_messages, username, mailCount)
    val styledText: Spanned = Html.fromHtml(text, FROM_HTML_MODE_LEGACY)
    

    Java

    String text = getString(R.string.welcome_messages, username, mailCount);
    Spanned styledText = Html.fromHtml(text, FROM_HTML_MODE_LEGACY);
    

เนื่องจากเมธอด fromHtml(String) จะจัดรูปแบบเอนทิตี HTML ทั้งหมด หลีกเลี่ยงอักขระ HTML ที่เป็นไปได้ในสตริงที่คุณใช้กับข้อความที่จัดรูปแบบ โดยใช้ htmlEncode(String) ตัวอย่างเช่น ถ้าคุณจัดรูปแบบสตริงที่มีอักขระ เช่น "<" หรือ "&" จะต้องกำหนดเป็นอักขระหลีกก่อนที่จะจัดรูปแบบ ดังนั้นเมื่อสตริงที่จัดรูปแบบแล้ว ส่งผ่าน fromHtml(String) ตัวละครจึงมีลักษณะเหมือน ที่เขียนขึ้นเป็นต้นฉบับ เช่น

Kotlin

val escapedUsername: String = TextUtils.htmlEncode(username)

val text: String = getString(R.string.welcome_messages, escapedUsername, mailCount)
val styledText: Spanned = Html.fromHtml(text, FROM_HTML_MODE_LEGACY)

Java

String escapedUsername = TextUtils.htmlEncode(username);

String text = getString(R.string.welcome_messages, escapedUsername, mailCount);
Spanned styledText = Html.fromHtml(text);

การจัดรูปแบบด้วยสับเปลี่ยน

Spannable คือออบเจ็กต์ข้อความที่คุณใช้จัดรูปแบบได้ คุณสมบัติของแบบอักษร เช่น สีและน้ำหนักของแบบอักษร คุณใช้ ใช้เวลาสร้าง SpannableStringBuilder ข้อความ แล้วใช้รูปแบบที่กำหนดไว้ใน android.text.style ลงในข้อความได้

คุณสามารถใช้วิธีการของตัวช่วยต่อไปนี้เพื่อตั้งค่างานส่วนใหญ่ได้ ของการสร้างข้อความแบบขยายได้

Kotlin

/**
 * Returns a CharSequence that concatenates the specified array of CharSequence
 * objects and then applies a list of zero or more tags to the entire range.
 *
 * @param content an array of character sequences to apply a style to
 * @param tags the styled span objects to apply to the content
 *        such as android.text.style.StyleSpan
 */
private fun apply(content: Array<out CharSequence>, vararg tags: Any): CharSequence {
    return SpannableStringBuilder().apply {
        openTags(tags)
        content.forEach { charSequence ->
            append(charSequence)
        }
        closeTags(tags)
    }
}

/**
 * Iterates over an array of tags and applies them to the beginning of the specified
 * Spannable object so that future text appended to the text will have the styling
 * applied to it. Do not call this method directly.
 */
private fun Spannable.openTags(tags: Array<out Any>) {
    tags.forEach { tag ->
        setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK)
    }
}

/**
 * "Closes" the specified tags on a Spannable by updating the spans to be
 * endpoint-exclusive so that future text appended to the end will not take
 * on the same styling. Do not call this method directly.
 */
private fun Spannable.closeTags(tags: Array<out Any>) {
    tags.forEach { tag ->
    if (length > 0) {
            setSpan(tag, 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        } else {
            removeSpan(tag)
        }
    }
}

Java

/**
 * Returns a CharSequence that concatenates the specified array of CharSequence
 * objects and then applies a list of zero or more tags to the entire range.
 *
 * @param content an array of character sequences to apply a style to
 * @param tags the styled span objects to apply to the content
 *        such as android.text.style.StyleSpan
 *
 */
private static CharSequence applyStyles(CharSequence[] content, Object[] tags) {
    SpannableStringBuilder text = new SpannableStringBuilder();
    openTags(text, tags);
    for (CharSequence item : content) {
        text.append(item);
    }
    closeTags(text, tags);
    return text;
}

/**
 * Iterates over an array of tags and applies them to the beginning of the specified
 * Spannable object so that future text appended to the text will have the styling
 * applied to it. Do not call this method directly.
 */
private static void openTags(Spannable text, Object[] tags) {
    for (Object tag : tags) {
        text.setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK);
    }
}

/**
 * "Closes" the specified tags on a Spannable by updating the spans to be
 * endpoint-exclusive so that future text appended to the end will not take
 * on the same styling. Do not call this method directly.
 */
private static void closeTags(Spannable text, Object[] tags) {
    int len = text.length();
    for (Object tag : tags) {
        if (len > 0) {
            text.setSpan(tag, 0, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        } else {
            text.removeSpan(tag);
        }
    }
}

bold, italic และ color ต่อไปนี้ รวมวิธีการของตัวช่วยข้างต้นและแสดงตัวอย่างเฉพาะของการนำไปใช้ รูปแบบที่กำหนดไว้ในแพ็กเกจ android.text.style คุณ สามารถสร้างวิธีที่คล้ายกันในการจัดรูปแบบข้อความประเภทอื่นๆ

Kotlin

/**
 * Returns a CharSequence that applies boldface to the concatenation
 * of the specified CharSequence objects.
 */
fun bold(vararg content: CharSequence): CharSequence = apply(content, StyleSpan(Typeface.BOLD))

/**
 * Returns a CharSequence that applies italics to the concatenation
 * of the specified CharSequence objects.
 */
fun italic(vararg content: CharSequence): CharSequence = apply(content, StyleSpan(Typeface.ITALIC))

/**
 * Returns a CharSequence that applies a foreground color to the
 * concatenation of the specified CharSequence objects.
 */
fun color(color: Int, vararg content: CharSequence): CharSequence =
        apply(content, ForegroundColorSpan(color))

Java

/**
 * Returns a CharSequence that applies boldface to the concatenation
 * of the specified CharSequence objects.
 */
public static CharSequence bold(CharSequence... content) {
    return apply(content, new StyleSpan(Typeface.BOLD));
}

/**
 * Returns a CharSequence that applies italics to the concatenation
 * of the specified CharSequence objects.
 */
public static CharSequence italic(CharSequence... content) {
    return apply(content, new StyleSpan(Typeface.ITALIC));
}

/**
 * Returns a CharSequence that applies a foreground color to the
 * concatenation of the specified CharSequence objects.
 */
public static CharSequence color(int color, CharSequence... content) {
    return apply(content, new ForegroundColorSpan(color));
}

มาดูตัวอย่างวิธีเชื่อมโยงวิธีการเหล่านี้เข้าด้วยกันเพื่อนำสไตล์ต่างๆ ไปใช้กับผลิตภัณฑ์แต่ละอย่าง คำที่อยู่ในวลี:

Kotlin

// Create an italic "hello, " a red "world",
// and bold the entire sequence.
val text: CharSequence = bold(italic(getString(R.string.hello)),
        color(Color.RED, getString(R.string.world)))

Java

// Create an italic "hello, " a red "world",
// and bold the entire sequence.
CharSequence text = bold(italic(getString(R.string.hello)),
    color(Color.RED, getString(R.string.world)));

โมดูล Core-ktx Kotlin ยังมีฟังก์ชันส่วนขยายที่ทำให้สามารถทำงานกับระยะเวลาได้ ได้ง่ายยิ่งขึ้น คุณสามารถดู เอกสารเกี่ยวกับแพ็กเกจ android.text ใน GitHub เพื่อดูข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับระยะเวลาได้ในลิงก์ต่อไปนี้

การจัดรูปแบบพร้อมคำอธิบายประกอบ

คุณสามารถใช้การจัดรูปแบบที่ซับซ้อนหรือที่กำหนดเองได้โดยใช้คลาส Annotation ร่วมกับ <annotation> ในไฟล์ทรัพยากร string.xml ของคุณ แท็กคำอธิบายประกอบช่วยให้ คุณสามารถทำเครื่องหมายส่วนต่างๆ ของสตริงสำหรับการจัดรูปแบบที่กำหนดเองโดยกำหนดคู่คีย์-ค่าที่กำหนดเองใน XML ที่เฟรมเวิร์กแปลงเป็น Annotation span จากนั้นคุณสามารถดู คำอธิบายประกอบ และใช้คีย์และค่าเพื่อใช้การจัดรูปแบบ

เมื่อสร้างคำอธิบายประกอบ อย่าลืมเพิ่ม <annotation> แท็กไปยังคำแปลทั้งหมดของสตริงในไฟล์ string.xml ทุกไฟล์


การใช้แบบอักษรที่กำหนดเองกับคำว่า "ข้อความ" ในทุกภาษา

ตัวอย่าง - การเพิ่มแบบตัวพิมพ์ที่กำหนดเอง

  1. เพิ่มแท็ก <annotation> แล้วกำหนดคู่คีย์-ค่า ในกรณีนี้ ค่า คีย์คือ font และค่าคือประเภทของแบบอักษรที่เราต้องการใช้: title_emphasis

    // values/strings.xml
    <string name="title">Best practices for <annotation font="title_emphasis">text</annotation> on Android</string>
    
    // values-es/strings.xml
    <string name="title"><annotation font="title_emphasis">Texto</annotation> en Android: mejores prácticas</string>
    
  2. โหลดทรัพยากรสตริงและค้นหาคำอธิบายประกอบด้วยคีย์ font จากนั้นสร้าง ระยะเวลาที่กำหนดเอง และแทนที่ระยะเวลาที่มีอยู่

    Kotlin

    // get the text as SpannedString so we can get the spans attached to the text
    val titleText = getText(R.string.title) as SpannedString
    
    // get all the annotation spans from the text
    val annotations = titleText.getSpans(0, titleText.length, Annotation::class.java)
    
    // create a copy of the title text as a SpannableString.
    // the constructor copies both the text and the spans. so we can add and remove spans
    val spannableString = SpannableString(titleText)
    
    // iterate through all the annotation spans
    for (annotation in annotations) {
       // look for the span with the key font
       if (annotation.key == "font") {
          val fontName = annotation.value
          // check the value associated to the annotation key
          if (fontName == "title_emphasis") {
             // create the typeface
             val typeface = getFontCompat(R.font.permanent_marker)
             // set the span at the same indices as the annotation
             spannableString.setSpan(CustomTypefaceSpan(typeface),
                titleText.getSpanStart(annotation),
                titleText.getSpanEnd(annotation),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
          }
       }
    }
    
    // now, the spannableString contains both the annotation spans and the CustomTypefaceSpan
    styledText.text = spannableString
    

    Java

    // get the text as SpannedString so we can get the spans attached to the text
    SpannedString titleText = (SpannedString) getText(R.string.title);
    
    // get all the annotation spans from the text
    Annotation[] annotations = titleText.getSpans(0, titleText.length(), Annotation.class);
    
    // create a copy of the title text as a SpannableString.
    // the constructor copies both the text and the spans. so we can add and remove spans
    SpannableString spannableString = new SpannableString(titleText);
    
    // iterate through all the annotation spans
    for (Annotation annotation: annotations) {
      // look for the span with the key font
      if (annotation.getKey().equals("font")) {
        String fontName = annotation.getValue();
        // check the value associated to the annotation key
        if (fontName.equals("title_emphasis")) {
        // create the typeface
        Typeface typeface = ResourcesCompat.getFont(this, R.font.roboto_mono);
        // set the span at the same indices as the annotation
        spannableString.setSpan(new CustomTypefaceSpan(typeface),
          titleText.getSpanStart(annotation),
          titleText.getSpanEnd(annotation),
          Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
      }
    }
    
    // now, the spannableString contains both the annotation spans and the CustomTypefaceSpan
    styledText.text = spannableString;
    

หากคุณใช้ข้อความเดียวกันหลายครั้ง คุณควรสร้าง ออบเจ็กต์ SpanoableString เพียงครั้งเดียว แล้วนำมาใช้ใหม่ตามความจำเป็นเพื่อหลีกเลี่ยงประสิทธิภาพและหน่วยความจำที่อาจเกิดขึ้น ปัญหา

ดูตัวอย่างเพิ่มเติมของการใช้คำอธิบายประกอบได้ที่ การจัดรูปแบบข้อความสากลใน Android

Span ของคำอธิบายประกอบและการแบ่งข้อความ

เนื่องจากช่วง Annotation ก็เป็น ParcelableSpans ด้วย ดังนั้นคีย์-ค่า เป็นคู่ที่แบ่งแล้วแบบแบ่งเป็นคู่ ตราบใดที่ผู้รับพัสดุทราบวิธีตีความ คำอธิบายประกอบ คุณสามารถใช้ระยะเวลา Annotation เพื่อนำการจัดรูปแบบที่กำหนดเองไปใช้กับองค์ประกอบ ข้อความที่แบ่งเป็นแถว

คุณต้องเพิ่มการจัดรูปแบบที่กำหนดเองเมื่อส่งข้อความไปที่กลุ่ม Intent ก่อน Annotation ครอบคลุมข้อความของคุณ โดยทำได้ในทรัพยากร XML ผ่านทาง <หมายเหตุ> ดังที่แสดงในตัวอย่างด้านบน หรือในโค้ดโดยการสร้างแท็ก Annotation และตั้งค่าเป็นระยะเวลา ดังที่แสดงด้านล่าง

Kotlin

val spannableString = SpannableString("My spantastic text")
val annotation = Annotation("font", "title_emphasis")
spannableString.setSpan(annotation, 3, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

// start Activity with text with spans
val intent = Intent(this, MainActivity::class.java)
intent.putExtra(TEXT_EXTRA, spannableString)
startActivity(intent)

Java

SpannableString spannableString = new SpannableString("My spantastic text");
Annotation annotation = new Annotation("font", "title_emphasis");
spannableString.setSpan(annotation, 3, 7, 33);

// start Activity with text with spans
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(TEXT_EXTRA, spannableString);
this.startActivity(intent);

ดึงข้อความจาก Bundle เป็น SpannableString แล้วแยกวิเคราะห์ คำอธิบายประกอบที่แนบมา ดังที่แสดงในตัวอย่างด้านบน

Kotlin

// read text with Spans
val intentCharSequence = intent.getCharSequenceExtra(TEXT_EXTRA) as SpannableString

Java

// read text with Spans
SpannableString intentCharSequence = (SpannableString)intent.getCharSequenceExtra(TEXT_EXTRA);

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการจัดรูปแบบข้อความ โปรดดูลิงก์ต่อไปนี้