Konsep dan penerapan Jetpack Compose
Resource string menyediakan string teks untuk aplikasi Anda dengan pemformatan dan penataan gaya teks opsional. Ada tiga jenis resource yang bisa menyediakan string untuk aplikasi Anda:
- String
- Resource XML yang menyediakan string tunggal.
- String Array
- Resource XML yang menyediakan array string.
- String Jumlah (Jamak)
- Resource XML yang membawa string berbeda untuk pluralisasi.
Semua string mampu menerapkan beberapa argumen markup penataan gaya dan pemformatan. Untuk informasi tentang string penataan gaya dan pemformatan, lihat bagian tentang Pemformatan dan Penataan Gaya.
String
String tunggal yang dapat direferensikan dari aplikasi atau dari file resource lain (seperti tata letak XML).
- lokasi file:
res/values/filename.xml
Nama file bersifat arbitrer.nameelemen<string>digunakan sebagai ID resource.- jenis data resource yang dihimpun:
- Pointer resource ke
String. - referensi resource:
-
Di Java:
R.string.string_name
Dalam XML:@string/string_name - sintaksis:
-
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="string_name" >text_string</string> </resources>
- elemen:
- contoh:
- File XML yang disimpan di
res/values/strings.xml:<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello!</string> </resources>
XML tata letak ini menerapkan string ke View:
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" />
Kode aplikasi ini mengambil sebuah string:
Anda bisa menggunakan
getString(int)ataugetText(int)untuk mengambil string.getText(int)akan mempertahankan penataan gaya rich text ke string.
Array string
Array string yang bisa direferensikan dari aplikasi.
- lokasi file:
res/values/filename.xml
Nama file bersifat arbitrer.nameelemen<string-array>digunakan sebagai ID resource.- jenis data resource yang dihimpun:
- Pointer resource ke array
String. - referensi resource:
-
Di Java:
R.array.string_array_name
Dalam XML:@[package:]array/string_array_name - sintaksis:
-
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="string_array_name"> <item >text_string</item> </string-array> </resources>
- elemen:
- contoh:
- File XML yang disimpan di
res/values/strings.xml: Kode aplikasi ini mengambil sebuah array string:<?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);
String jumlah (jamak)
Bahasa yang berbeda memiliki aturan yang berbeda pula untuk kesepakatan gramatikal pada jumlah. Dalam bahasa Inggris, misalnya, jumlah 1 adalah kasus khusus. Kita menulis
"1 buku", tetapi untuk jumlah lain kita akan menulis "n buku". Perbedaan antara tunggal dan jamak sudah sangat umum, tetapi bahasa lain membuat perbedaan yang lebih tipis. Set lengkap yang didukung Android adalah zero, one, two, few,
many, dan other.
Aturan untuk memutuskan kasus mana yang akan digunakan untuk bahasa dan jumlah yang diberikan boleh jadi akan sangat kompleks, jadi Android menyediakan beberapa metode seperti getQuantityString() untuk memilih resource yang sesuai untuk Anda.
Di API 24+, Anda dapat menggunakan class MessageFormat
ICU yang jauh lebih canggih.
- lokasi file:
res/values/filename.xml
Nama file bersifat arbitrer.nameelemen<plurals>digunakan sebagai ID resource.- referensi resource:
-
Di Java:
R.plurals.plural_name - sintaksis:
-
<?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>
- elemen:
- contoh:
- File XML yang disimpan di
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>
File XML yang disimpan di
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>
Penggunaan:
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);Saat menggunakan metode
getQuantityString(), Anda perlu meneruskancountdua kali jika string Anda berisi pemformatan string. Misalnya, untuk string%d songs found, parametercountpertama akan memilih string jamak yang sesuai dan parametercountkedua akan dimasukkan ke dalam placeholder%d. Jika string jamak Anda tidak berisi pemformatan string, Anda tidak perlu meneruskan parameter ketiga kegetQuantityString.
Format dan gaya
Berikut beberapa hal penting yang harus Anda ketahui tentang cara yang benar untuk memformat dan menata gaya resource string.
Memformat string
Jika perlu memformat string, Anda dapat melakukannya dengan menempatkan argumen format dalam resource string, seperti yang ditunjukkan oleh resource contoh berikut.
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
Dalam contoh ini, string format memiliki dua argumen: %1$s adalah string dan
%2$d adalah bilangan desimal. Kemudian, format string dengan memanggil
getString(int, Object...). Contoh:
Kotlin
var text = getString(R.string.welcome_messages, username, mailCount)
Java
String text = getString(R.string.welcome_messages, username, mailCount);
Menata gaya dengan markup HTML
Anda bisa menambahkan penataan gaya ke string dengan markup HTML. Contoh:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="welcome">Welcome to <b>Android</b>!</string> </resources>
Jika tidak menerapkan pemformatan, Anda dapat menyetel teks TextView secara langsung dengan
memanggil setText(java.lang.CharSequence). Akan tetapi, kadang-kadang Anda mungkin
ingin membuat resource teks bergaya yang juga digunakan sebagai string format.
Biasanya, hal ini tidak akan berhasil karena metode format(String, Object...) dan
getString(int, Object...) akan melucuti semua informasi gaya dari
string. Solusinya adalah menuliskan tag HTML dengan entitas yang dikurung, yang nanti dipulihkan dengan fromHtml(String), setelah
pemformatan dilakukan. Contoh:
- Simpan resource teks bergaya sebagai string yang dikurung dengan HTML:
<resources> <string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string> </resources>
Dalam string yang diformat ini, elemen
<b>telah ditambahkan. Perhatikan bahwa kurung buka adalah HTML yang di-escape, dengan menggunakan notasi<. - Kemudian format string tersebut seperti biasa, namun panggil juga
fromHtml(String)untuk mengonversi teks HTML menjadi teks yang diberi gaya: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);
Karena metode fromHtml(String) memformat semua entity HTML, pastikan
untuk meng-escape semua karakter HTML yang memungkinkan dalam string yang Anda gunakan bersama teks
berformat, menggunakan htmlEncode(String). Misalnya, jika Anda memformat
string yang berisi karakter seperti "<" atau "&", string tersebut harus
di-escape sebelum diformat, sehingga saat string berformat diteruskan melalui
fromHtml(String), karakter tersebut muncul sebagaimana aslinya. Contoh:
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);Menata gaya dengan spannable
Spannable adalah objek teks yang dapat Anda beri gaya dengan properti typeface
seperti warna dan ketebalan font. Anda menggunakan SpannableStringBuilder untuk mem-build
teks kemudian menerapkan gaya yang ditetapkan dalam paket
android.text.style ke teks.
Anda dapat menggunakan metode helper berikut untuk menyiapkan sebagian besar pekerjaan membuat teks spannable:
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); } } }
Metode bold, italic, dan color berikut menggabungkan metode helper di atas dan memperagakan contoh tertentu mengenai penerapan gaya yang ditetapkan dalam paket android.text.style. Anda dapat membuat metode serupa untuk melakukan penataan gaya jenis teks lainnya.
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)); }
Berikut ini contoh cara menghubungkan metode ini bersama-sama untuk menerapkan berbagai gaya ke masing-masing kata dalam frasa:
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)));
Modul Kotlin core-ktx juga berisi fungsi ekstensi yang membuat bekerja dengan span jadi
lebih mudah. Anda dapat melihat dokumentasi paket android.text di GitHub untuk mempelajari lebih lanjut.
Untuk informasi selengkapnya tentang menggunakan span, lihat link berikut:
Menata gaya dengan anotasi
Anda dapat menerapkan penataan gaya kompleks atau khusus dengan menggunakan class Annotation bersama dengan tag <annotation> dalam file resource strings.xml Anda. Tag
anotasi memungkinkan Anda menandai bagian string untuk penataan gaya khusus dengan
menentukan pasangan nilai kunci khusus dalam XML yang kemudian dikonversi framework
ke span Annotation. Selanjutnya, Anda dapat mengambil anotasi ini dan menggunakan
kunci dan nilai untuk menerapkan penataan gaya.
Saat membuat anotasi, pastikan Anda menambahkan tag <annotation>
ke semua penerjemahan string dalam setiap file strings.xml.

Menerapkan typeface khusus ke kata "text" dalam semua bahasa
Contoh - menambahkan typeface khusus
-
Tambahkan tag
<annotation>, dan pasangan nilai kunci. Dalam hal ini, kunci adalah font, dan nilai adalah jenis font yang ingin kita gunakan: 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>
-
Muat resource string dan temukan anotasi dengan kunci font. Kemudian buat span khusus dan ganti span yang ada.
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;
Jika menggunakan teks yang sama beberapa kali, Anda harus membuat objek SpannableString sekali dan menggunakannya lagi saat diperlukan untuk menghindari potensi masalah performa dan memori.
Untuk contoh selengkapnya tentang penggunaan anotasi, lihat Menata gaya teks yang diinternasionalisasikan di Android.
Span anotasi dan pembagian teks
Karena rentang Annotation juga ParcelableSpans, pasangan nilai kunci
dibagi dan tidak dibagi. Selama penerima pembagian mengetahui cara menafsirkan
anotasi, Anda dapat menggunakan rentang Annotation untuk menerapkan penataan gaya
khusus ke teks yang dibagi.
Untuk menyimpan penataan gaya khusus saat Anda meneruskan teks ke Paket Intent, Anda
terlebih dahulu perlu menambahkan span Annotation ke teks Anda. Anda dapat melakukannya di resource XML melalui tag <annotation>, seperti yang ditunjukkan dalam contoh di atas, atau di kode dengan membuat Annotation baru dan menyetelnya sebagai span, seperti yang ditunjukkan di bawah:
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);
Ambil teks dari Bundle sebagai SpannableString, lalu uraikan anotasi yang dilampirkan, seperti yang ditunjukkan dalam contoh di atas.
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);
Untuk informasi selengkapnya tentang penataan gaya teks, lihat link berikut: