משאבי מחרוזת

משאב מחרוזות מספק מחרוזות טקסט לאפליקציה עם עיצוב ועיצוב טקסט אופציונליים. יש שלושה סוגי משאבים שיכולים לספק את האפליקציה באמצעות מחרוזות:

String
משאב XML שמספק מחרוזת יחידה.
מערך מחרוזות
משאב XML שמספק מערך של מחרוזות.
מחרוזות כמות (Plurals)
משאב XML שנושא מחרוזות שונות לצורך רבים.

כל המחרוזות יכולות להחיל חלק מתגי העיצוב והארגומנטים של העיצוב. עבור מידע על עיצוב ועיצוב מחרוזות, עיינו בקטע עיצוב ועיצוב.

מחרוזת

מחרוזת יחידה שאפשר להפנות אליה מהאפליקציה או מקובצי משאבים אחרים (כמו כפריסת XML).

הערה: מחרוזת היא משאב פשוט שיש הפניה אליו באמצעות הערך שצוין במאפיין name (לא השם של קובץ ה-XML). אפשר לשלב משאבי מחרוזות עם משאבים פשוטים אחרים בקובץ XML יחיד, תחת רכיב <resources> אחד.

מיקום הקובץ:

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>
חובה. הוא חייב להיות צומת הרמה הבסיסית (root).

אין מאפיינים.

<string>
מחרוזת, שיכולה לכלול תגי עיצוב. זהירות: עליך לסמן בתו בריחה (escape) במירכאות. מידע נוסף על עיצוב ועיצוב מתאימים של מחרוזות זמין בקטע עיצוב ועיצוב בהמשך.

:

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) שומר.

מערך מחרוזות

מערך של מחרוזות שאפשר להפנות אליהן מהאפליקציה.

הערה: מערך מחרוזת הוא משאב פשוט שיש אליו הפניה באמצעות הערך שצוין במאפיין name (לא השם של קובץ ה-XML). בתור לדוגמה, אפשר לשלב משאבים של מערך מחרוזות עם משאבים פשוטים אחרים בקובץ XML אחד, תחת רכיב <resources> אחד.

מיקום הקובץ:

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>
חובה. הוא חייב להיות צומת הרמה הבסיסית (root).

אין מאפיינים.

<string-array>
מגדירה מערך של מחרוזות. מכיל רכיב <item> או יותר.

:

name
מחרוזת. שם למערך. השם הזה משמש בתור המשאב המזהה שיפנה למערך.
<item>
מחרוזת, שיכולה לכלול תגי עיצוב. הערך יכול להיות הפניה לערך אחר משאב מחרוזות. חייב להיות צאצא של רכיב <string-array>. זהירות! צריך לסמן בתו בריחה (escape) במירכאות. למידע נוסף, ראו עיצוב ועיצוב מידע על הסגנון והעיצוב הנכון של המחרוזות.

אין מאפיינים.

דוגמא:
קובץ 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 היא מקרה מיוחד. אנחנו כותבים "ספר אחד", אבל עבור כל כמות אחרת לכתוב "n Books". ההבחנה בין יחיד לרבים נפוצה מאוד, אך יוצרים הבחנות עדינות יותר. הקבוצה המלאה שנתמכת ב-Android היא zero, one, two, few, many וגם other.

הכללים שקובעים באיזה מקרה להשתמש עבור שפה וכמות מסוימים יכולים להיות מורכבים מאוד, אז Android מספק לך שיטות כמו getQuantityString() כדי לבחור מקור המידע המתאים.

למרות שנקראו בעבר 'מחרוזות כמות', (וזה עדיין נקרא ב-API), כמות צריך להשתמש במחרוזות רק עבור צורת רבים. זאת טעות במחרוזות כמות להטמיע משהו כמו "תיבת הדואר הנכנס" של Gmail לעומת 'תיבת דואר נכנס (12)' כשיהיו הודעות שלא נקראו, לדוגמה. אולי כדאי להשתמש במחרוזות כמות במקום בהצהרת if, אבל חשוב לציין שחלק מהשפות (כמו סינית) לא הופכות את הדקדוק שונים, כך שתמיד תקבלו את המחרוזת other.

בחירת המחרוזת לשימוש מתבצעת אך ורק על סמך הצורך הדקדוקי. באנגלית, המערכת מתעלמת ממחרוזת של zero גם אם הכמות היא 0, כי 0 שאינו שונה מבחינה דקדוקית מ-2, או מכל מספר אחר מלבד 1 ("אפס ספרים", "ספר אחד", 'שני ספרים', וכן הלאה). לעומת זאת, בקוריאנית רק המחרוזת other שהיו בשימוש אי פעם.

אל תטעה את זה, כי, למשל, two נשמע כאילו הוא יכול לחול רק על הכמות 2: שפה יכולה לדרוש שגם 2, 12, 102 (וכן הלאה) יטופלו כמו אחת כמויות שונות, אבל באופן שונה מכמויות אחרות. הסתמכו על המתרגם לשמוע את ההבדלים השפה שלהם ממש מתעקשת.

אם ההודעה לא מכילה את מספר הכמות, סביר להניח שהיא לא מועמדת טובה רבים. לדוגמה, בליטאית משתמשים בצורת יחיד גם לספר 1 וגם למספר 101, כך ש"ספר אחד" תואם לערך מתורגמים ל-"1 knyga" ו-"101 Books" מתורגם ל-"101 knyga". בינתיים, 'ספר' הוא 'knyga' ו'ספרים רבים' הוא 'daug knygיוו'. אם הודעה בצורת רבים באנגלית מכילה את המילה 'ספר' (יחיד) ו'ספרים רבים' (רבים) ללא את המספר האמיתי, אפשר לתרגם אותו ל-"knyga" (abook)/"daug knygử" (ספרים רבים), אבל לפי כללי ליטא, יוצג השם knyga (ספר יחיד), כשהמספר הוא 101.

בדרך כלל ניתן להימנע ממחרוזות כמות על ידי שימוש בנוסחאות ניטרליות, כגון "ספרים: 1". כך החיים שלכם ושל המתרגמים חיים לקלים יותר, אם זה סגנון שמתאים לאפליקציה שלכם.

ב-API 24 ואילך אפשר להשתמש ביחידה הארגונית MessageFormat במכשיר רב יותר-עוצמה במקום זאת.

הערה: אוסף צורת רבים הוא משאב פשוט מפנים באמצעות הערך שצוין במאפיין name (לא שם ה-XML ). לכן, ניתן לשלב משאבים בצורת רבים עם משאבים פשוטים אחרים קובץ XML, ברכיב <resources> אחד.

מיקום הקובץ:

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>
חובה. הוא חייב להיות צומת הרמה הבסיסית (root).

אין מאפיינים.

<plurals>
אוסף של מחרוזות, שמתוכו מחרוזת אחת סופקה בהתאם לכמות או משהו. מכיל רכיב <item> או יותר.

:

name
מחרוזת. השם של זוג המחרוזות. השם הזה משמש למזהה המשאב של הממשק.
<item>
מחרוזת יחיד או רבים. הערך יכול להיות הפניה לערך אחר משאב מחרוזות. חייב להיות צאצא של רכיב <plurals>. זהירות! גרשיים ומירכאות. למידע נוסף, אפשר לעיין בקטע עיצוב ו עיצוב בהמשך לקבלת מידע על עיצוב ועיצוב מתאימים של מחרוזות.

:

quantity
מילת מפתח. ערך שמציין מתי יש להשתמש במחרוזת הזו. נתונים תקפים עם דוגמאות חלקיות בסוגריים:
ערךתיאור
zeroכאשר השפה דורשת יחס מיוחד למספר 0 (כמו בערבית).
oneכאשר השפה דורשת יחס מיוחד למספרים כגון אחד (כמו הספרה 1 באנגלית וברוב השפות האחרות; ברוסית, כל מספר שמסתיים ב-1 ולא מסתיים ב-11 נמצא במחלקה הזו).
twoכאשר השפה דורשת יחס מיוחד למספרים כמו שני מספרים (כמו 2 בוולשית או 102 בסלובנית).
fewכאשר השפה דורשת יחס מיוחד ל'קטן' מספרים (כמו 2, 3 ו-4 בצ'כית, או מספרים שמסתיימים ב-2, 3 או 4 אבל לא בפולנית 12, 13 או 14).
manyכשהשפה דורשת יחס מיוחד למילה 'large' מספרים (כמו במספרים המסתיימים ב-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 פעמיים אם המחרוזת כוללת פורמט מחרוזות עם מספר. לדוגמה, עבור המחרוזת. %d songs found, הפרמטר count הראשון בוחר את מחרוזת הרבים המתאימה הפרמטר count השני נוסף ל-placeholder של %d. אם רבים המחרוזות לא כוללות את פורמט המחרוזת. אין צורך להעביר את הפרמטר השלישי אל getQuantityString.

פורמט וסגנון

הנה כמה דברים חשובים שכדאי לדעת כדי להבין איך לעצב ולעצב את משאבי המחרוזת.

טיפול בתווים מיוחדים

כאשר מחרוזת מכילה תווים שיש להם שימוש מיוחד ב-XML, צריך לסמן בתו בריחה (escape) את בהתאם לכללי ה-escape הרגילים של XML/HTML. אם צריך לסמן תו בתו בריחה (escape) שיש לו משמעות מיוחדת ב-Android, עליך להשתמש לפניו לוכסן הפוך.

כברירת מחדל, מערכת Android תכווץ רצפים של תווי רווח לבן לרווח יחיד. כדי למנוע מצב כזה, צריך להקיף את החלק הרלוונטי במחרוזת במירכאות כפולות. במקרה הזה כל תווי הרווח הלבן (כולל שורות חדשות) יישמרו בתוך האזור המצוטט. אפשר להשתמש במירכאות כפולות כדי להשתמש גם במירכאות רגילות ללא תו בריחה (escape).

תו טפסים מילוט
@ \@
? \?
שורה חדשה \n
מקש Tab \t
תו U+XXXX Unicode \uXXXX
גרש בודד (')

אחד מהפרטים הבאים:

  • \'
  • צריך לתחום את כל המחרוזת במירכאות כפולות (למשל, "This'll work")
מירכאות כפולות (") \"

חשוב לשים לב שהמופע של המחרוזת במירכאות בודדות לא פועל.

כיווץ רווחים לבנים ופעולת בריחה מ-Android מתרחשת אחרי קובץ המשאב ינותח כ-XML. המשמעות היא <string> &#32; &#8200; &#8195;</string> (רווח, רווח פיסוק, רווח Unicode Em) כולם כיווץ לרווח אחד (" "), כי כל הרווחים הם רווחים מ-Unicode אחרי ניתוח הקובץ כ-XML. כדי לשמור את הרווחים האלה כפי שהם, אפשר לצטט אותם. (<string>" &#32; &#8200; &#8195;"</string>) אפשר גם להשתמש ב-Android Escape (<string> \u0032 \u8200 \u8195</string>).

הערה: מבחינת מנתח XML, אין הבדל בין <string>"Test this"</string> והקבוצה <string>&quot;Test this&quot;</string> בכלל. שני הטפסים לא יציג מירכאות, אלא יפעיל ציטוט ששומר על רווחים לבנים ב-Android (שלא יכלול בפועל במקרה הזה).

עיצוב מחרוזות

אם צריך לעצב את המחרוזות, אפשר לעשות את זה באמצעות הצבת הארגומנטים של פורמט במשאב המחרוזת, כפי שאפשר לראות במשאב לדוגמה הבא.

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

בדוגמה הזו, מחרוזת הפורמט כוללת שני ארגומנטים: %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>, <cite>, <dfn>, <em>
  • טקסט גדול יותר ב-25%: <large>
  • טקסט קטן ב-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=”...”>

אם לא משתמשים בעיצוב, אפשר להגדיר את הטקסט ב-TextView ישירות באמצעות התקשרות setText(java.lang.CharSequence) עם זאת, במקרים מסוימים ייתכן רוצים ליצור משאב טקסט מסוגנן שמשמש גם כמחרוזת עיצוב. בדרך כלל, לא פועלת כי format(String, Object...) ו- getString(int, Object...) השיטות מסירות את כל הסגנון מהמחרוזת. דרך לעקוף את הבעיה היא לכתוב את תגי ה-HTML עם תווי בריחה (escape) ישויות, שאפשר לשחזר באמצעות fromHtml(String), אחרי קביעת הפורמט. לדוגמה:

  1. שומרים את משאב הטקסט המעוצב כמחרוזת HTML עם בריחה (escape):
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    במחרוזת המעוצבת הזו, נוסף רכיב <b>. שימו לב שהסוגריים הפותחים הם סימון HTML בתו בריחה (escape), באמצעות הסימון &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, לכן חשוב להקפיד לסמן בתו בריחה (escape) כל תו HTML אפשרי במחרוזות שבהן משתמשים בטקסט המעוצב, באמצעות htmlEncode(String). לדוגמה, אם אתם מעצבים מחרוזת שמכילה תווים כמו '<' או '&', צריך לסמן אותם בתו בריחה (escape) לפני הפורמט. כך, כשהמחרוזת המעוצבת מועבר דרך 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

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 מכיל גם פונקציות תוסף שהופכות את העבודה עם spans ל- יותר קל. אפשר לעיין מידע נוסף על חבילת android.text ב-GitHub.

למידע נוסף על עבודה עם spans, עיינו בקישורים הבאים:

עיצוב עם הערות

אפשר להחיל עיצוב מורכב או מותאם אישית באמצעות המחלקה Annotation ביחד עם <annotation> בקובצי המשאבים מסוג String.xml. תג ההערה מאפשר לסמן חלקים מהמחרוזת לעיצוב מותאם אישית על ידי הגדרת צמדי מפתח/ערך מותאמים אישית ב-XML שה-framework ממיר ל-Annotation מתפרשת על פני טווח. לאחר מכן אפשר לאחזר את הנתונים האלה הערות ומשתמשים במפתח ובערך כדי להחיל את הסגנון.

כשיוצרים הערות, חשוב להוסיף את <annotation> תג לכל התרגומים של המחרוזת בכל קובץ string.xml.


החלת משפחת גופנים בהתאמה אישית על המילה 'text' בכל השפות

דוגמה – הוספת משפחת גופנים מותאמת אישית

  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;
    

אם אתם משתמשים באותו טקסט מספר פעמים, צריך ליצור את אובייקט SpannableString פעם אחת ועושה בו שימוש חוזר לפי הצורך, כדי למנוע ביצועים וזיכרון פוטנציאליים בעיות נפוצות.

לדוגמאות נוספות של שימוש בהערות: עיצוב טקסט בינלאומי ב-Android

טווחי הערות ומגרשי טקסט

בגלל שהפרצופים של 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);

למידע נוסף על עיצוב טקסט, אפשר לעיין בקישורים הבאים: