منابع رشته‌ای (Views)

مفاهیم و پیاده‌سازی Jetpack Compose

یک منبع رشته‌ای، رشته‌های متنی را برای برنامه شما با استایل و قالب‌بندی متن اختیاری فراهم می‌کند. سه نوع منبع وجود دارد که می‌توانند رشته‌ها را در اختیار برنامه شما قرار دهند:

رشته
منبع XML که یک رشته واحد ارائه می‌دهد.
آرایه رشته‌ای
منبع XML که آرایه‌ای از رشته‌ها را ارائه می‌دهد.
رشته‌های مقداری (جمع)
منبع XML که رشته‌های مختلفی را برای جمع‌بندی حمل می‌کند.

همه رشته‌ها قابلیت اعمال برخی از آرگومان‌های نشانه‌گذاری و قالب‌بندی استایل را دارند. برای اطلاعات بیشتر در مورد استایل‌بندی و قالب‌بندی رشته‌ها، به بخش مربوط به قالب‌بندی و استایل‌بندی مراجعه کنید.

رشته

یک رشته واحد که می‌تواند از برنامه یا از سایر فایل‌های منبع (مانند طرح‌بندی XML) ارجاع داده شود.

محل فایل:
res/values/ filename .xml
نام فایل دلخواه است. name عنصر <string> به عنوان شناسه منبع استفاده می‌شود.
نوع داده منبع کامپایل شده:
اشاره‌گر منبع به یک String .
مرجع منابع:
در جاوا: 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
رشته . نامی برای رشته. این نام به عنوان شناسه منبع استفاده می‌شود.
مثال:
فایل 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" />

این کد برنامه یک رشته را بازیابی می‌کند:

کاتلین

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

جاوا

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

شما می‌توانید از getString(int) یا getText(int) برای بازیابی یک رشته استفاده کنید. getText(int) هرگونه استایل متن غنی اعمال شده روی رشته را حفظ می‌کند.

آرایه رشته‌ای

آرایه‌ای از رشته‌ها که می‌توان از طریق برنامه به آنها ارجاع داد.

محل فایل:
res/values/ filename .xml
نام فایل دلخواه است. name عنصر <string-array> به عنوان شناسه منبع استفاده می‌شود.
نوع داده منبع کامپایل شده:
اشاره‌گر منبع به آرایه‌ای از String .
مرجع منابع:
در جاوا: 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> است.

ویژگی‌ها:

name
String . نامی برای آرایه. این نام به عنوان شناسه منبع برای ارجاع به آرایه استفاده می‌شود.
<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>
این کد برنامه یک آرایه رشته‌ای را بازیابی می‌کند:

کاتلین

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

جاوا

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

رشته‌های مقداری (جمع)

زبان‌های مختلف، قوانین متفاوتی برای تطابق دستوری با کمیت دارند. برای مثال، در انگلیسی، کمیت ۱ یک مورد خاص است. ما می‌نویسیم "۱ کتاب"، اما برای هر کمیت دیگری می‌نویسیم " n کتاب". این تمایز بین مفرد و جمع بسیار رایج است، اما زبان‌های دیگر تمایزات دقیق‌تری قائل می‌شوند. مجموعه کامل پشتیبانی شده توسط اندروید شامل zero ، one ، two ، few ، many و other است.

قوانین مربوط به تصمیم‌گیری در مورد اینکه کدام حالت برای یک زبان و مقدار مشخص استفاده شود، می‌تواند بسیار پیچیده باشد، بنابراین اندروید متدهایی مانند getQuantityString() را برای انتخاب منبع مناسب در اختیار شما قرار می‌دهد.

در API 24+ می‌توانید به جای آن از کلاس بسیار قدرتمندتر ICU MessageFormat استفاده کنید.

محل فایل:
res/values/ filename .xml
نام فایل دلخواه است. name عنصر <plurals> به عنوان شناسه منبع استفاده می‌شود.
مرجع منابع:
در جاوا: 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>
مجموعه‌ای از رشته‌ها که از بین آنها، یک رشته بسته به مقدار چیزی ارائه می‌شود. شامل یک یا چند عنصر <item> است.

ویژگی‌ها:

name
String . نامی برای جفت رشته‌ها. این نام به عنوان شناسه منبع استفاده می‌شود.
</dd>

<item>
یک رشته جمع یا مفرد. مقدار می‌تواند ارجاعی به یک منبع رشته‌ای دیگر باشد. باید فرزند یک عنصر <plurals> باشد. توجه داشته باشید که باید آپاستروف و علامت نقل قول را escape کنید. برای کسب اطلاعات در مورد نحوه صحیح استایل‌بندی و قالب‌بندی رشته‌های خود، به بخش قالب‌بندی و استایل‌بندی در زیر مراجعه کنید.

ویژگی‌ها:

quantity
کلمه کلیدی . مقداری که نشان می‌دهد این رشته چه زمانی باید استفاده شود. مقادیر معتبر، با مثال‌های غیرجامع در داخل پرانتز:
ارزش توضیحات
zero وقتی زبان، رفتار خاصی با عدد ۰ (مانند عربی) می‌طلبد.
one وقتی زبان، رفتار خاصی با اعدادی مانند یک را می‌طلبد (مانند عدد ۱ در انگلیسی و اکثر زبان‌های دیگر؛ در روسی، هر عددی که به ۱ ختم می‌شود اما به ۱۱ ختم نمی‌شود، در این دسته قرار می‌گیرد).
two وقتی زبان، برخورد ویژه‌ای با اعدادی مانند دو را می‌طلبد (مثل عدد ۲ در زبان ولزی یا عدد ۱۰۲ در زبان اسلوونیایی).
few وقتی زبان، برخورد ویژه‌ای با اعداد «کوچک» را ایجاب می‌کند (مانند ۲، ۳ و ۴ در زبان چک؛ یا اعدادی که به ۲، ۳ یا ۴ ختم می‌شوند اما به ۱۲، ۱۳ یا ۱۴ ختم نمی‌شوند در زبان لهستانی).
many وقتی زبان، رفتار ویژه‌ای با اعداد «بزرگ» را ایجاب می‌کند (مانند اعدادی که در زبان مالتی به ۱۱ تا ۹۹ ختم می‌شوند).
other وقتی زبان مربوطه، رفتار خاصی با کمیت داده شده نداشته باشد (مانند همه اعداد در چینی یا ۴۲ در انگلیسی).

مثال:
فایل 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>

کاربرد:

کاتلین

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

جاوا

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

هنگام استفاده از متد getQuantityString() ، اگر رشته شما شامل قالب‌بندی رشته‌ای باشد، باید مقدار count را دو بار ارسال کنید. برای مثال، برای رشته %d songs found ، پارامتر count اول، رشته جمع مناسب را انتخاب می‌کند و پارامتر count دوم در متغیر %d قرار می‌گیرد. اگر رشته‌های جمع شما شامل قالب‌بندی رشته‌ای نباشند، نیازی به ارسال پارامتر سوم به getQuantityString نیست.

قالب و سبک

در اینجا چند نکته مهم وجود دارد که باید در مورد نحوه قالب‌بندی و استایل‌دهی صحیح منابع رشته‌ای خود بدانید.

قالب‌بندی رشته‌ها

اگر نیاز به قالب‌بندی رشته‌های خود دارید، می‌توانید این کار را با قرار دادن آرگومان‌های قالب‌بندی خود در منبع رشته انجام دهید، همانطور که در مثال منبع زیر نشان داده شده است.

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

در این مثال، رشته‌ی فرمت دو آرگومان دارد: %1$s یک رشته و %2$d یک عدد اعشاری است. سپس، رشته را با فراخوانی getString(int, Object...) فرمت کنید. برای مثال:

کاتلین

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

جاوا

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>

اگر قالب‌بندی را اعمال نمی‌کنید، می‌توانید متن TextView را مستقیماً با فراخوانی setText(java.lang.CharSequence) تنظیم کنید. با این حال، در برخی موارد، ممکن است بخواهید یک منبع متن استایل‌بندی شده ایجاد کنید که به عنوان یک رشته فرمت نیز استفاده شود. معمولاً این کار جواب نمی‌دهد زیرا متدهای format(String, Object...) و getString(int, Object...) تمام اطلاعات استایل را از رشته حذف می‌کنند. راه حل این مشکل، نوشتن تگ‌های HTML با موجودیت‌های escape شده است که پس از انجام قالب‌بندی، با fromHtml(String) بازیابی می‌شوند. به عنوان مثال:

  1. منبع متنی استایل‌دهی شده خود را به عنوان یک رشته HTML-escaped ذخیره کنید:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>

    در این رشته‌ی قالب‌بندی‌شده، یک عنصر <b> اضافه شده است. توجه داشته باشید که براکت آغازین با استفاده از نمادگذاری &lt; از نوع HTML-escaped است.

  2. سپس رشته را طبق معمول قالب‌بندی کنید، اما همچنین fromHtml(String) را برای تبدیل متن HTML به متن استایل‌دار فراخوانی کنید:

    کاتلین

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

    جاوا

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

از آنجا که متد fromHtml(String) تمام موجودیت‌های HTML را قالب‌بندی می‌کند، حتماً با استفاده از htmlEncode(String) هر کاراکتر HTML ممکن را در رشته‌هایی که با متن قالب‌بندی شده استفاده می‌کنید، escape کنید. برای مثال، اگر در حال قالب‌بندی رشته‌ای هستید که حاوی کاراکترهایی مانند "<" یا "&" است، باید قبل از قالب‌بندی escape شوند، به طوری که وقتی رشته قالب‌بندی شده از fromHtml(String) عبور داده می‌شود، کاراکترها به همان شکلی که در ابتدا نوشته شده‌اند، ظاهر شوند. برای مثال:

کاتلین

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)

جاوا

String escapedUsername = TextUtils.htmlEncode(username);

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

استایل دادن با اسپانبل‌ها

یک Spannable یک شیء متنی است که می‌توانید آن را با ویژگی‌های typeface مانند رنگ و وزن فونت، استایل‌دهی کنید. شما SpannableStringBuilder برای ساخت متن خود استفاده می‌کنید و سپس استایل‌های تعریف شده در پکیج android.text.style را به متن اعمال می‌کنید.

شما می‌توانید از متدهای کمکی زیر برای تنظیم بخش عمده‌ای از کار ایجاد متن spannable استفاده کنید:

کاتلین

/**
 * 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)
        }
    }
}

جاوا

/**
 * 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 را نشان می‌دهند. می‌توانید متدهای مشابهی برای انجام انواع دیگر استایل‌بندی متن ایجاد کنید.

کاتلین

/**
 * 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))

جاوا

/**
 * 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));
}

در اینجا مثالی از نحوه‌ی ترکیب این متدها برای اعمال سبک‌های مختلف به کلمات منفرد در یک عبارت آورده شده است:

کاتلین

// 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)))

جاوا

// 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 کاتلین همچنین شامل توابع افزونه‌ای است که کار با spanها را آسان‌تر می‌کند. برای کسب اطلاعات بیشتر می‌توانید مستندات بسته android.text را در گیت‌هاب بررسی کنید.

برای اطلاعات بیشتر در مورد کار با اسپن‌ها، به لینک‌های زیر مراجعه کنید:

استایل‌دهی با حاشیه‌نویسی

شما می‌توانید با استفاده از کلاس Annotation به همراه تگ <annotation> در فایل‌های منبع strings.xml خود، استایل‌بندی پیچیده یا سفارشی اعمال کنید. تگ annotation به شما این امکان را می‌دهد که با تعریف جفت‌های کلید-مقدار سفارشی در XML که فریم‌ورک سپس به Annotation spans تبدیل می‌کند، بخش‌هایی از رشته را برای استایل‌بندی سفارشی علامت‌گذاری کنید. سپس می‌توانید این annotationها را بازیابی کرده و از کلید و مقدار برای اعمال استایل‌بندی استفاده کنید.

هنگام ایجاد حاشیه‌نویسی‌ها، مطمئن شوید که برچسب <annotation> را به تمام ترجمه‌های رشته در هر فایل strings.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. منبع رشته را بارگذاری کنید و حاشیه‌نویسی‌ها را با کلید فونت پیدا کنید. سپس یک span سفارشی ایجاد کنید و span موجود را جایگزین کنید.

    کاتلین

    // 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

    جاوا

    // 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 را بسازید و در صورت نیاز دوباره از آن استفاده کنید تا از مشکلات احتمالی عملکرد و حافظه جلوگیری شود.

برای مثال‌های بیشتر از کاربرد حاشیه‌نویسی، به «طراحی متن بین‌المللی‌شده در اندروید» مراجعه کنید.

حاشیه‌نویسی و دسته‌بندی متن

از آنجا که Annotation spans نیز ParcelableSpans هستند، جفت‌های کلید-مقدار به صورت parceled و unparceled هستند. تا زمانی که گیرنده‌ی parcel بداند چگونه annotationها را تفسیر کند، می‌توانید Annotation spans برای اعمال استایل‌بندی سفارشی به متن parceled استفاده کنید.

برای حفظ استایل سفارشی خود هنگام ارسال متن به یک Intent Bundle، ابتدا باید Annotation spans را به متن خود اضافه کنید. می‌توانید این کار را در منابع XML از طریق تگ <annotation> انجام دهید، همانطور که در مثال بالا نشان داده شده است، یا در کد با ایجاد یک Annotation جدید و تنظیم آن به عنوان span، همانطور که در زیر نشان داده شده است:

کاتلین

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)

جاوا

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 بازیابی کنید و سپس حاشیه‌نویسی‌های پیوست شده را تجزیه کنید، همانطور که در مثال بالا نشان داده شده است.

کاتلین

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

جاوا

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

برای اطلاعات بیشتر در مورد سبک متن، به لینک‌های زیر مراجعه کنید: