ทรัพยากรสตริงมีสตริงข้อความสำหรับแอปพลิเคชันของคุณพร้อมการจัดรูปแบบและจัดสไตล์ข้อความที่ไม่บังคับ มีทรัพยากร 3 ประเภทที่สามารถให้สตริงแก่แอปพลิเคชัน ของคุณได้
- สตริง
- ทรัพยากร XML ที่มีสตริงเดียว
- อาร์เรย์สตริง
- ทรัพยากร XML ที่มีอาร์เรย์ของสตริง
- สตริงจำนวน (คำนามพหูพจน์)
- ทรัพยากร XML ที่มีสตริงต่างๆ สำหรับการเปลี่ยนคำให้เป็นพหูพจน์
สตริงทั้งหมดสามารถใช้มาร์กอัปการจัดรูปแบบและอาร์กิวเมนต์ การจัดรูปแบบบางอย่างได้ ดูข้อมูลเกี่ยวกับการจัดรูปแบบและจัดรูปแบบสตริงได้ในส่วนการจัดรูปแบบและการจัดสไตล์
สตริง
สตริงเดียวที่อ้างอิงได้จากโค้ดของแอปพลิเคชัน (เช่น ฟังก์ชันที่ประกอบกันได้) หรือจากไฟล์ทรัพยากรอื่นๆ
- ตำแหน่งไฟล์:
res/values/filename.xml
ชื่อไฟล์เป็นชื่อใดก็ได้ ระบบจะใช้nameขององค์ประกอบ<string>เป็น รหัสทรัพยากร- ประเภทข้อมูลทรัพยากรที่คอมไพล์แล้ว:
- ตัวชี้ทรัพยากรไปยัง
String - การอ้างอิงทรัพยากร
-
ใน Kotlin:
R.string.string_name
ใน XML:@string/string_name - ไวยากรณ์:
-
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="string_name" >text_string</string> </resources>
- องค์ประกอบ
- ตัวอย่าง:
- บันทึกไฟล์ XML ที่
res/values/strings.xmlแล้ว<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello!</string> </resources>
โค้ดของแอปพลิเคชันนี้ดึงสตริงจากภายใน Composable ด้วย
stringResource()@Composable fun Greeting() { Text(text = stringResource(R.string.hello)) }
หมายเหตุ: หากต้องการดึงสตริงนอกฟังก์ชันที่ประกอบกันได้ ให้ใช้
นอกจากนี้ คุณยังอ้างอิงทรัพยากรสตริงจากไฟล์ XML อื่นๆ ได้ด้วย เช่นcontext.getString(R.string.hello)AndroidManifest.xml<activity android:name=".MainActivity" android:label="@string/hello" />
อาร์เรย์สตริง
อาร์เรย์ของสตริงที่อ้างอิงได้จากแอปพลิเคชัน
- ตำแหน่งไฟล์:
res/values/filename.xml
ชื่อไฟล์เป็นชื่อใดก็ได้ ระบบจะใช้nameขององค์ประกอบ<string-array>เป็น รหัสทรัพยากร- ประเภทข้อมูลทรัพยากรที่คอมไพล์แล้ว:
- ตัวชี้ทรัพยากรไปยังอาร์เรย์ของ
Strings - การอ้างอิงทรัพยากร
-
ใน Kotlin:
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>
- องค์ประกอบ
- ตัวอย่าง:
- บันทึกไฟล์ 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>
โค้ดของแอปพลิเคชันนี้จะดึงอาร์เรย์สตริงจากภายใน Composable ด้วย
stringArrayResource()@Composable fun PlanetList() { val planets: Array
= stringArrayResource(R.array.planets_array) // Render the array, e.g. inside a LazyColumn. } หมายเหตุ: หากต้องการดึงข้อมูลอาร์เรย์สตริงนอกฟังก์ชันที่ประกอบกันได้ ให้ใช้
context.resources.getStringArray(R.array.planets_array)
สตริงจำนวน (คำนามพหูพจน์)
ภาษาต่างๆ มีกฎที่แตกต่างกันสำหรับการตกลงทางไวยากรณ์กับปริมาณ เช่น ในภาษาอังกฤษ จำนวน 1 เป็นกรณีพิเศษ เราเขียนว่า "หนังสือ 1 เล่ม" แต่หากมีจำนวนอื่น เราจะเขียนว่า "หนังสือ n เล่ม" ความแตกต่าง
ระหว่างเอกพจน์และพหูพจน์เป็นเรื่องปกติมาก แต่ภาษาอื่นๆ มีความแตกต่างที่ละเอียดกว่า
ชุดอักขระทั้งหมดที่ Android รองรับคือ zero, one, two, few,
many และ other
กฎในการตัดสินใจว่าจะใช้รูปแบบใดสำหรับภาษาและจำนวนที่กำหนดอาจมีความซับซ้อนมาก ดังนั้น Android จึงมีวิธีการต่างๆ เช่น pluralStringResource() เพื่อให้คุณเลือกทรัพยากรที่เหมาะสมได้
แม้ว่าในอดีตจะเรียกว่า "สตริงจำนวน" (และยังคงเรียกว่าสตริงจำนวนใน API)
แต่สตริงจำนวนควรใช้สำหรับคำที่เป็นพหูพจน์เท่านั้น การใช้สตริงจำนวนเพื่อใช้ฟีเจอร์อย่างเช่น "กล่องจดหมาย" ของ Gmail กับ "กล่องจดหมาย (12)" เมื่อมีข้อความที่ยังไม่ได้อ่านเป็นตัวอย่างถือเป็นข้อผิดพลาด การใช้สตริงจำนวนแทนคำสั่ง if อาจดูสะดวก แต่โปรดทราบว่าบางภาษา (เช่น จีน) ไม่มีการแยกความแตกต่างทางไวยากรณ์เหล่านี้เลย ดังนั้นคุณจะได้รับสตริง other เสมอ
การเลือกสตริงที่จะใช้จะขึ้นอยู่กับความจำเป็นทางไวยากรณ์เท่านั้น ในภาษาอังกฤษ ระบบจะไม่สนใจสตริงสำหรับ zero แม้ว่าจำนวนจะเป็น 0 ก็ตาม เนื่องจาก 0 ไม่ได้แตกต่างจาก 2 หรือตัวเลขอื่นๆ ยกเว้น 1 ในแง่ของไวยากรณ์ ("zero books", "one book", "two books" และอื่นๆ) ในทางกลับกัน ในภาษาเกาหลี เท่านั้นที่จะใช้สตริง other
อย่าเข้าใจผิดว่า two ใช้ได้กับจำนวน 2 เท่านั้น เพราะภาษาอาจกำหนดให้ 2, 12, 102 (และอื่นๆ) มีลักษณะเหมือนกัน แต่แตกต่างจากจำนวนอื่นๆ พึ่งพา
นักแปลเพื่อดูว่าภาษาของตนมีข้อแตกต่างที่สำคัญอะไรบ้าง
หากข้อความไม่มีหมายเลขจำนวน ก็อาจไม่เหมาะที่จะใช้เป็นคำพหูพจน์ เช่น ในภาษาลิทัวเนียจะใช้รูปแบบเอกพจน์สำหรับทั้ง 1 และ 101 ดังนั้น "หนังสือ 1 เล่ม" จะแปลเป็น "1 knyga" และ "หนังสือ 101 เล่ม" จะแปลเป็น "101 knyga" ในขณะที่ "a book" คือ "knyga" และ "many books" คือ "daug knygų" หากข้อความภาษาอังกฤษแบบพหูพจน์มีคำว่า "a book" (เอกพจน์) และ "many books" (พหูพจน์) โดยไม่มีตัวเลขจริง คุณจะแปลเป็น "knyga" (หนังสือ 1 เล่ม)/"daug knygų" (หนังสือหลายเล่ม) ได้ แต่ตามกฎของลิทัวเนีย ระบบจะแสดง "knyga" (หนังสือ 1 เล่ม) เมื่อตัวเลขเป็น 101
โดยปกติแล้ว คุณสามารถหลีกเลี่ยงสตริงจำนวนได้โดยใช้รูปแบบที่เป็นกลางต่อจำนวน เช่น "Books: 1" ซึ่งจะช่วยให้ชีวิตคุณและชีวิตของนักแปลง่ายขึ้น หากเป็นรูปแบบที่ยอมรับได้สำหรับแอปพลิเคชันของคุณ
ใน API 24 ขึ้นไป คุณสามารถใช้คลาส MessageFormat ของ ICU ที่มีประสิทธิภาพมากกว่าแทนได้
- ตำแหน่งไฟล์:
res/values/filename.xml
ชื่อไฟล์เป็นชื่อใดก็ได้ ระบบจะใช้nameขององค์ประกอบ<plurals>เป็น รหัสทรัพยากร- การอ้างอิงทรัพยากร
-
ใน Kotlin:
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>
- องค์ประกอบ
- ตัวอย่าง:
บันทึกไฟล์ 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>
โค้ดของแอปพลิเคชันนี้จะดึงสตริงพหูพจน์จากภายใน Composable ด้วย
pluralStringResource()@Composable fun SongCount(count: Int) { Text( text = pluralStringResource( R.plurals.numberOfSongsAvailable, count, count, ) ) }
เมื่อใช้ฟังก์ชัน
pluralStringResource()คุณต้องส่งcount2 ครั้งหากสตริงมีการจัดรูปแบบสตริงที่มีตัวเลข ตัวอย่างเช่น สำหรับสตริง%d songs foundพารามิเตอร์countแรกจะเลือกสตริงพหูพจน์ที่เหมาะสม และ พารามิเตอร์countที่ 2 จะแทรกลงในตัวยึดตำแหน่ง%dหากสตริง พหูพจน์ไม่มีการจัดรูปแบบสตริง คุณไม่จำเป็นต้องส่งพารามิเตอร์ที่ 3 ไปยังpluralStringResourceหมายเหตุ: หากต้องการดึงสตริงพหูพจน์นอกฟังก์ชันที่ประกอบกันได้ ให้ใช้
context.resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count)
รูปแบบและสไตล์
สิ่งสำคัญที่ควรทราบเกี่ยวกับวิธีจัดรูปแบบและจัดรูปแบบทรัพยากรสตริงอย่างถูกต้องมีดังนี้
จัดการอักขระพิเศษ
เมื่อสตริงมีอักขระที่มีการใช้งานพิเศษใน XML คุณต้อง หลีกเลี่ยงอักขระตามกฎการหลีกเลี่ยง XML/HTML มาตรฐาน หากต้องการกำหนดอักขระที่มีความหมายพิเศษใน Android เป็นอักขระหลีก คุณควรใช้แบ็กสแลชนำหน้า
โดยค่าเริ่มต้น Android จะยุบลำดับของอักขระช่องว่างเป็น ช่องว่างเดียว คุณหลีกเลี่ยงปัญหานี้ได้โดยการใส่เครื่องหมายคำพูดคู่คร่อมส่วนที่เกี่ยวข้องของสตริง ในกรณีนี้ ระบบจะเก็บอักขระช่องว่างทั้งหมด (รวมถึงบรรทัดใหม่) ไว้ภายในภูมิภาคที่อ้างอิง เครื่องหมายคำพูดคู่จะช่วยให้คุณ ใช้เครื่องหมายคำพูดเดี่ยวปกติที่ไม่ได้หลีกได้ด้วย
| ตัวละคร | รูปแบบที่หลีกเลี่ยง |
|---|---|
| @ | \@ |
| ? | \? |
| บรรทัดใหม่ | \n |
| แท็บ | \t |
| อักขระ Unicode U+XXXX | \uXXXX |
เครื่องหมายคำพูดเดี่ยว (') |
รายการใดก็ได้ต่อไปนี้
|
เครื่องหมายคำพูดคู่ (") |
\"
โปรดทราบว่าการใส่เครื่องหมายคำพูดเดี่ยวรอบสตริงจะใช้ไม่ได้ |
การยุบช่องว่างและการหลีกอักขระใน Android จะเกิดขึ้นหลังจากที่ระบบแยกวิเคราะห์ไฟล์ทรัพยากรเป็น XML
ซึ่งหมายความว่า <string>      </string>
(ช่องว่าง, ช่องว่างเครื่องหมายวรรคตอน, ช่องว่าง Unicode Em) จะยุบรวมเป็นช่องว่างเดียว
(" ") เนื่องจากทั้งหมดเป็นช่องว่าง Unicode หลังจากแยกวิเคราะห์ไฟล์เป็น XML
หากต้องการคงช่องว่างเหล่านั้นไว้ตามเดิม คุณสามารถใส่เครื่องหมายคำพูด
(<string>"      "</string>)
หรือใช้การหลีกอักขระใน Android
(<string> \u0032 \u8200 \u8195</string>)
การจัดรูปแบบสตริง
หากต้องการจัดรูปแบบสตริง คุณสามารถทำได้โดยใส่รูปแบบ อาร์กิวเมนต์ในทรัพยากรสตริง ดังที่แสดงในตัวอย่าง ทรัพยากรต่อไปนี้
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
โค้ดของแอปพลิเคชันนี้จัดรูปแบบสตริงจากภายใน Composable โดยการส่งอาร์กิวเมนต์ไปยัง stringResource() โดยตรง
@Composable fun WelcomeMessage(username: String, mailCount: Int) { Text( text = stringResource( 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>,<cite>,<dfn>,<em> - ข้อความใหญ่ขึ้น 25%:
<big> - ข้อความเล็กลง 20%:
<small> - การตั้งค่าพร็อพเพอร์ตี้แบบอักษร:
<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="…">
ในบางกรณี คุณอาจต้องการสร้างทรัพยากรข้อความที่มีสไตล์ซึ่งใช้เป็นสตริงรูปแบบด้วย
โดยปกติแล้ว วิธีนี้จะใช้ไม่ได้เนื่องจากวิธีการจัดรูปแบบ
เช่น stringResource() จะลบข้อมูลรูปแบบทั้งหมดออกจากสตริง
วิธีแก้ปัญหานี้คือการเขียนแท็ก HTML ด้วยเอนทิตีที่หลบหนี ซึ่งจะกู้คืนด้วย AnnotatedString.fromHtml() หลังจากจัดรูปแบบแล้ว เช่น
- จัดเก็บทรัพยากรข้อความที่มีการจัดรูปแบบเป็นสตริงที่หลีกเลี่ยง HTML ดังนี้
<resources> <string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string> </resources>
ในสตริงที่จัดรูปแบบนี้ ระบบจะเพิ่มองค์ประกอบ
<b>โปรดทราบว่าวงเล็บเปิดจะได้รับการหลีกเลี่ยง HTML โดยใช้สัญกรณ์< - จากนั้นจัดรูปแบบสตริงตามปกติ แต่ให้เรียกใช้
AnnotatedString.fromHtml()เพื่อ แปลงข้อความ HTML เป็นสตริง Compose ที่จัดรูปแบบ
เนื่องจาก fromHtml() จัดรูปแบบเอนทิตี HTML ทั้งหมด โปรดตรวจสอบว่าได้กำหนดอักขระหลีกสำหรับอักขระ HTML ที่เป็นไปได้ในสตริงที่คุณใช้กับข้อความที่จัดรูปแบบแล้วโดยใช้ TextUtils.htmlEncode()
import android.text.TextUtils import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.fromHtml @Composable fun WelcomeHtmlMessage(username: String, mailCount: Int) { // Escape the username in case it contains characters like "<" or "&" val escapedUsername = TextUtils.htmlEncode(username) val text = stringResource( R.string.welcome_messages, escapedUsername, mailCount, ) Text( text = AnnotatedString.fromHtml(text) ) }
การจัดรูปแบบด้วย AnnotatedString
AnnotatedString คือออบเจ็กต์ข้อความ Compose ที่คุณจัดรูปแบบได้ด้วย
พร็อพเพอร์ตี้ เช่น สีและความหนาของแบบอักษร สร้างข้อความที่มีสไตล์โดยใช้โปรแกรม
โดยใช้ buildAnnotatedString และ withStyle
โค้ดของแอปพลิเคชันนี้สร้างองค์ประกอบของข้อความเดียวที่มีรูปแบบผสม ดังนี้
@Composable fun StyledGreeting() { val styled = buildAnnotatedString { append("Welcome to ") withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { append("Android") } append("!") } Text(text = styled) }
หากต้องการใช้สี ขนาดแบบอักษร และการตกแต่งข้อความ ให้ใช้ SpanStyle หากต้องการใช้การจัดรูปแบบระดับย่อหน้า (เช่น การจัดแนวหรือระยะห่างระหว่างบรรทัด) ให้ใช้ ParagraphStyle
@Composable fun RichText() { val text = buildAnnotatedString { withStyle(ParagraphStyle(lineHeight = 24.sp, textAlign = TextAlign.Center)) { withStyle(SpanStyle(color = Color.Gray)) { append("Hello, ") } withStyle( SpanStyle( fontWeight = FontWeight.Bold, color = Color.Red, ) ) { append("world") } append("!") } } Text(text = text) }
การสร้าง AnnotatedString โดยตรงเป็นแนวทางที่แนะนำสำหรับ
แอปภาษาเดียวหรือข้อความแบบคงที่ใน Compose อย่างไรก็ตาม สำหรับข้อความที่มีการจัดรูปแบบซึ่ง
ต้องมีการแปล โปรดดูแนวทาง XML <annotation> ที่อธิบายไว้โดยละเอียดในส่วนถัดไป
การจัดรูปแบบสตริงที่แปลด้วยคำอธิบายประกอบ
สำหรับสตริงที่ต้องมีการจัดรูปแบบและการแปลที่กำหนดเอง ให้กำหนดแท็ก
<annotation> ใน strings.xml ของแต่ละภาษา นักแปลจะคง
คำอธิบายประกอบไว้ไม่ว่าจะอยู่ในส่วนใดของประโยค อ่านสตริงด้วย
context.resources.getText() เดินตามช่วง Annotation และแปลง
ผลลัพธ์เป็น AnnotatedString
@Composable fun AnnotatedTitle() { val context = LocalContext.current val source = context.resources.getText(R.string.title) as SpannedString val text = buildAnnotatedString { append(source.toString()) source.getSpans(0, source.length, Annotation::class.java) .forEach { annotation -> if (annotation.key == "font" && annotation.value == "title_emphasis") { addStyle( SpanStyle( fontFamily = FontFamily( Font(R.font.permanent_marker) ) ), source.getSpanStart(annotation), source.getSpanEnd(annotation), ) } } } Text(text = text) }
แท็ก <annotation> ใน XML จะไม่มีการเปลี่ยนแปลง มีเพียงรหัสการดึงข้อมูลเท่านั้นที่แตกต่างกัน
นักแปลยังคงย้ายแท็กเพื่อครอบคำที่ถูกต้องในแต่ละภาษาได้
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรสตริงได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้