منابع رشته ای

یک منبع رشته رشته های متنی را برای برنامه شما با یک ظاهر طراحی و قالب بندی متن اختیاری فراهم می کند. سه نوع منبع وجود دارد که می توانند رشته های برنامه شما را ارائه دهند:

رشته
منبع XML که یک رشته را فراهم می کند.
آرایه رشته ای
منبع XML که آرایه ای از رشته ها را فراهم می کند.
رشته های کمیت (جمع)
منبع XML که رشته های مختلفی را برای کثرت سازی حمل می کند.

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

رشته

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

نکته: رشته یک منبع ساده است که با استفاده از مقدار ارائه شده در ویژگی name (نه نام فایل XML) به آن ارجاع داده می شود. بنابراین، می توانید منابع رشته ای را با سایر منابع ساده در یک فایل XML، تحت یک عنصر <resources> ترکیب کنید.

محل فایل:
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 یک رشته را به یک View اعمال می کند:

<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) هر نوع استایل متن غنی اعمال شده روی رشته را حفظ می کند.

آرایه رشته ای

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

توجه: آرایه رشته ای منبع ساده ای است که با استفاده از مقدار ارائه شده در ویژگی name (نه نام فایل XML) به آن ارجاع داده می شود. به این ترتیب، می توانید منابع آرایه رشته ای را با سایر منابع ساده در یک فایل XML، تحت یک عنصر <resources> ترکیب کنید.

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

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

کاتلین

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

جاوا

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

رشته های کمیت (جمع)

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

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

اگرچه از نظر تاریخی "رشته های کمیت" نامیده می شود (و هنوز در API به آن گفته می شود)، رشته های کمیت فقط باید برای جمع استفاده شوند. برای مثال وقتی پیام‌های خوانده‌نشده وجود دارد، استفاده از رشته‌های کمیت برای پیاده‌سازی چیزی مانند «صندوق ورودی» جیمیل در مقابل «صندوق ورودی (12)» اشتباه است. ممکن است استفاده از رشته های کمیت به جای دستور if راحت به نظر برسد، اما توجه به این نکته مهم است که برخی از زبان ها (مانند چینی) اصلاً این تمایزات گرامری را انجام نمی دهند، بنابراین همیشه رشته other را دریافت خواهید کرد.

انتخاب رشته مورد استفاده صرفاً بر اساس ضرورت گرامری انجام می شود. در زبان انگلیسی، رشته ای برای zero نادیده گرفته می شود، حتی اگر مقدار آن 0 باشد، زیرا 0 از نظر گرامری با 2 یا هر عدد دیگری به جز 1 ("صفر کتاب"، "یک کتاب"، "دو کتاب" و غیره متفاوت است. در). برعکس، در کره ای فقط از رشته other استفاده می شود.

با این واقعیت که مثلاً two صدا مانند آن فقط می‌تواند برای کمیت 2 صدق کند، گمراه نشوید: ممکن است یک زبان مستلزم این باشد که 2، 12، 102 (و غیره) همه شبیه یکدیگر باشند، اما با دیگران متفاوت رفتار شود. مقادیر به مترجم خود تکیه کنید تا بدانید زبان او واقعاً بر چه تمایزاتی اصرار دارد.

اگر پیام شما حاوی عدد کمیت نیست، احتمالاً کاندیدای مناسبی برای جمع نیست. به عنوان مثال، در لیتوانیایی از شکل مفرد برای 1 و 101 استفاده می شود، بنابراین "1 کتاب" به عنوان "1 knyga" و "101 books" به عنوان "101 knyga" ترجمه می شود. در ضمن "یک کتاب" "knyga" و "کتابهای بسیار" "daug knygų" است. اگر یک پیام جمع انگلیسی حاوی "یک کتاب" (مفرد) و "کتاب های زیادی" (جمع) بدون عدد واقعی باشد، می توان آن را به عنوان "knyga" (یک کتاب)/"daug knygų" (کتاب های زیادی) ترجمه کرد، اما با قوانین لیتوانیایی، زمانی که عدد 101 باشد، "knyga" (یک کتاب) را نشان می دهد.

اغلب می‌توان با استفاده از فرمول‌بندی‌های کمیت خنثی مانند «کتاب‌ها: 1» از رشته‌های کمیت اجتناب کرد. این کار زندگی شما و مترجمانتان را آسان‌تر می‌کند، اگر سبک قابل قبولی برای برنامه شما باشد.

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

توجه: مجموعه جمع یک منبع ساده است که با استفاده از مقدار ارائه شده در ویژگی name (نه نام فایل XML) به آن ارجاع داده می شود. به این ترتیب، می توانید منابع جمع را با سایر منابع ساده در یک فایل XML، تحت یک عنصر <resources> ترکیب کنید.

محل فایل:
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
رشته . نامی برای جفت رشته. این نام به عنوان شناسه منبع استفاده می شود.
<item>
رشته جمع یا مفرد. مقدار می تواند مرجعی به منبع رشته ای دیگر باشد. باید فرزند عنصر <plurals> باشد. مراقب باشید که باید از آپستروف و علامت نقل قول فرار کنید. برای اطلاعات در مورد استایل و قالب بندی صحیح رشته های خود به قالب بندی و استایل کردن در زیر مراجعه کنید.

صفات:

quantity
کلمه کلیدی مقداری که نشان می دهد چه زمانی باید از این رشته استفاده شود. مقادیر معتبر، با مثال های غیر جامع داخل پرانتز:
ارزش توضیحات
zero هنگامی که زبان نیاز به برخورد خاصی با عدد 0 دارد (مانند عربی).
one زمانی که زبان نیاز به برخورد خاصی با اعدادی مانند یک دارد (مانند عدد 1 در انگلیسی و بسیاری از زبان‌های دیگر؛ در روسی، هر عددی که به 1 ختم می‌شود اما به 11 ختم نمی‌شود در این کلاس است).
two زمانی که زبان نیاز به برخورد خاصی با اعدادی مانند دو دارد (مانند 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>

استفاده:

کاتلین

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 منتقل کنید.

قالب و سبک

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

کاراکترهای خاص را مدیریت کنید

هنگامی که یک رشته دارای کاراکترهایی است که کاربرد خاصی در XML دارند، باید طبق قوانین استاندارد فرار XML/HTML از کاراکترها فرار کنید. اگر نیاز به فرار از شخصیتی دارید که در اندروید معنای خاصی دارد، باید از بک اسلش قبلی استفاده کنید.

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

شخصیت فرم(های) فرار شده
@ \@
? \?
خط جدید \n
Tab \t
نویسه U+XXXX یونیکد \uXXXX
نقل قول تکی ( ' )

هر یک از موارد زیر:

  • \'
  • کل رشته را در دو گیومه قرار دهید (برای مثال "This'll work" )
نقل قول دوگانه ( " ) \"

توجه داشته باشید که احاطه کردن رشته با نقل قول تکی کار نمی کند.

پس از اینکه فایل منبع شما به عنوان XML تجزیه می شود، فضای خالی و فرار اندروید اتفاق می افتد. این بدان معناست که <string> &#32; &#8200; &#8195;</string> (فضا، فضای نقطه گذاری، فضای Unicode Em) همه به یک فضای منفرد ( " " ) جمع می شوند، زیرا پس از تجزیه فایل به عنوان XML، همه آنها فضاهای یونیکد هستند. برای حفظ آن فضاها همانطور که هستند، می توانید آنها را نقل قول کنید ( <string>" &#32; &#8200; &#8195;"</string> ) یا از Android escaping استفاده کنید ( <string> \u0032 \u8200 \u8195</string> ).

توجه: از دیدگاه تجزیه کننده XML، هیچ تفاوتی بین <string>"Test this"</string> و <string>&quot;Test this&quot;</string> وجود ندارد. هر دو فرم هیچ نقل قولی را نشان نمی دهند اما نقل قول حفظ فضای خالی اندروید را فعال می کنند (که در این مورد هیچ اثر عملی نخواهد داشت).

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

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

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

عناصر HTML زیر پشتیبانی می شوند:

  • پررنگ: <b>
  • کج: <i>، <cite>، <dfn>، <em>
  • 25% متن بزرگتر: <بزرگ>
  • 20٪ متن کوچکتر: <small>
  • تنظیم ویژگی های قلم: <font face=”font_family“ color=”hex_color”>. نمونه هایی از خانواده فونت های ممکن عبارتند از monospace ، serif و sans_serif .
  • تنظیم یک خانواده فونت monospace: <tt>
  • Strikethrough: <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-Escape ذخیره کنید:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    در این رشته فرمت شده، یک عنصر <b> اضافه می شود. توجه داشته باشید که براکت باز شده با استفاده از &lt; نشانه گذاری

  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 را قالب‌بندی می‌کند، مطمئن شوید که از هر کاراکتر HTML احتمالی در رشته‌هایی که با متن قالب‌بندی شده استفاده می‌کنید، با استفاده از htmlEncode(String) فرار کنید. به عنوان مثال، اگر رشته‌ای را قالب‌بندی می‌کنید که حاوی کاراکترهایی مانند «<» یا «&» است، باید قبل از قالب‌بندی، آنها را حذف کنید، به طوری که وقتی رشته قالب‌بندی‌شده از 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);

یک ظاهر طراحی شده با spannables

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

می‌توانید از روش‌های کمکی زیر برای تنظیم بسیاری از کارهای ایجاد متن قابل استفاده استفاده کنید:

کاتلین

/**
 * 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 Kotlin همچنین دارای توابع پسوندی است که کار با دهانه ها را آسان تر می کند. برای کسب اطلاعات بیشتر می توانید اسناد بسته android.text را در GitHub بررسی کنید.

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

یک ظاهر طراحی شده با حاشیه نویسی

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

هنگام ایجاد حاشیه نویسی، مطمئن شوید که تگ <annotation> را به تمام ترجمه های رشته در هر فایل strings.xml اضافه می کنید.


اعمال یک تایپ فیس سفارشی برای کلمه "متن" در همه زبان ها

مثال - اضافه کردن یک تایپ فیس سفارشی

  1. تگ <annotation> را اضافه کنید و جفت کلید-مقدار را تعریف کنید. در این مورد، کلید فونت است و مقدار آن نوع فونتی است که می خواهیم استفاده کنیم: 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 را یک بار بسازید و در صورت نیاز مجدداً از آن استفاده کنید تا از مشکلات احتمالی عملکرد و حافظه جلوگیری کنید.

برای مثال‌های بیشتر از استفاده از حاشیه‌نویسی، سبک‌دهی به متن بین‌المللی شده در Android را ببینید

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

از آنجا که دهانه های Annotation نیز ParcelableSpans هستند، جفت های کلید-مقدار بسته بندی و بدون بسته بندی می شوند. تا زمانی که گیرنده بسته می داند چگونه حاشیه نویسی ها را تفسیر کند، می توانید از دهانه های Annotation برای اعمال یک استایل سفارشی به متن بسته بندی شده استفاده کنید.

برای حفظ استایل سفارشی خود هنگام ارسال متن به Intent Bundle، ابتدا باید دامنه Annotation را به متن خود اضافه کنید. می توانید این کار را در منابع 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);

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