موارد السلسلة

يوفر مورد السلاسل سلاسل نصية لتطبيقك مع تصميم وتنسيق نصي اختياري. هناك ثلاثة أنواع من الموارد التي يمكن أن تزود تطبيقك بالسلاسل:

String
مورد XML يوفر سلسلة واحدة
مصفوفة السلاسل
مورد XML يوفّر مجموعة من السلاسل.
سلاسل الكمية (الصيغ الزخرفية)
مورد 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>
يجب ملء هذا الحقل. يجب أن تكون هذه هي العقدة الجذر.

ما مِن سمات.

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

يسترد رمز التطبيق هذا سلسلة:

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> كرقم تعريف المورد.
نوع بيانات المورد المجمّع:
مؤشر المورد إلى مصفوفة من Strings.
مرجع للموارد:
في لغة 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>
يجب ملء هذا الحقل. يجب أن تكون هذه هي العقدة الجذر.

ما مِن سمات.

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

يسترد رمز التطبيق هذا صفيف سلسلة:

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 كتاب". إن هذا التمييز بين المفرد والجمع شائع جدًا، ولكن اللغات الأخرى تفسر فواصل أكثر دقة. المجموعة الكاملة المتوافقة مع Android هي zero وone وtwo وfew وmany وother.

قد تكون قواعد تحديد الحالة التي سيتم استخدامها للغة وكمية معيّنة معقّدة للغاية، لذلك يوفّر لك Android طرقًا مثل getQuantityString() لاختيار المورد المناسب لك.

على الرغم من أن سلاسل الكمية تُسمى في السابق "سلاسل الكمية" (ولا تزال تسمى ذلك في واجهة برمجة التطبيقات)، يجب استخدام سلاسل الكمية فقط لصيغ الجمع. سيكون من الخطأ استخدام سلاسل الكمية لتنفيذ شيء مثل "البريد الوارد" في Gmail مقابل "البريد الوارد (12)" عندما تكون هناك رسائل غير مقروءة، على سبيل المثال. قد يبدو من المناسب استخدام السلاسل الكمية بدلاً من عبارة if، لكن بعض اللغات (مثل الصينية) لا تستخدم هذه التناقضات النحوية على الإطلاق، لذلك ستحصل دائمًا على السلسلة other.

يتم اختيار السلسلة المطلوب استخدامها بناءً على الضرورة النحوية فقط. في اللغة الإنجليزية، يتم تجاهل سلسلة zero حتى إذا كانت الكمية 0، لأنّ 0 لا يختلف نحويًا عن 2، أو أي رقم آخر باستثناء 1 ("صفر كتب" و"كتاب واحد" و"كتابان" وما إلى ذلك). بالمقابل، في اللغة الكورية، يتم استخدام سلسلة other فقط فقط.

ويجب عدم تضليل المستخدم من خلال أنّه، مثلاً، يبدو أنّ السمة two تنطبق فقط على الكمية 2، فقد تتطلّب اللغة أن يتم التعامل مع الرقم 2 و12 و102 (وما إلى ذلك) بالطريقة نفسها، ولكن بطريقة مختلفة عن الكميات الأخرى. اعتمِد على المترجم للتعرُّف على الفروق التي تبرزها لغتهم.

إذا لم تكن رسالتك تحتوي على رقم الكمية، فمن المحتمل أنها لا تتناسب مع صيغة الجمع. على سبيل المثال، في الليتوانية يتم استخدام صيغة المفرد لكل من 1 و101، لذلك تتم ترجمة "كتاب واحد" على النحو التالي "1 knyga"، بينما تتم ترجمة "101 كتاب" على أنها "101 knyga". في حين أن "الكتاب" هو "knyga" و "العديد من الكتب" هو "daug knyg مشاهدي". إذا كانت رسالة الجمع باللغة الإنجليزية تحتوي على "كتاب" (مفرد) و "عدّة كتب" بدون العدد الفعلي، يمكن ترجمتها على أنّها "knyga" (كتاب)/"daug knyg مشاهدي" (العديد من الكتب)، ولكن وفقًا للقواعد الليتوانية، ستعرض العبارة "knyga" (كتاب واحد) عندما يكون العدد 101.

غالبًا ما يكون من الممكن تجنب السلاسل الكمية باستخدام صيغ محايدة كمية مثل "الكتب: 1". وهذا يجعل حياتك وحياة المترجمين أسهل إذا كان أسلوبًا مقبولاً للطلب.

في واجهة برمجة التطبيقات 24 والإصدارات الأحدث، يمكنك استخدام فئة MessageFormat لوحدة ICU الأكثر فعالية بدلاً من ذلك.

ملاحظة: مجموعة صيغ الجمع هي مورد بسيط تتم الإشارة إليه باستخدام القيمة المقدّمة في السمة 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>
يجب ملء هذا الحقل. يجب أن تكون هذه هي العقدة الجذر.

ما مِن سمات.

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

الاستخدام:

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 الثانية في العنصر النائب %d. إذا كانت سلاسل الجمع لا تتضمّن تنسيق سلسلة، لن تحتاج إلى تمرير المعلَمة الثالثة إلى getQuantityString.

التنسيق والنمط

فيما يلي بعض الأشياء المهمة التي يجب أن تعرفها حول كيفية تنسيق موارد السلسلة وتصميمها بشكل صحيح.

التعامل مع الرموز الخاصة

عندما تحتوي السلسلة على أحرف لها استخدام خاص في XML، عليك إلغاء هذه الأحرف وفقًا لقواعد الهروب العادية بتنسيق XML/HTML. وإذا كنت بحاجة إلى إلغاء حرف له معنى خاص في نظام Android، عليك استخدام شرطة مائلة للخلف.

سيصغّر Android تلقائيًا تسلسلات أحرف المسافات البيضاء في مساحة واحدة. يمكنك تجنب ذلك عن طريق تضمين الجزء ذي الصلة من السلسلة بين علامتي اقتباس. وفي هذه الحالة، سيتم الاحتفاظ بجميع أحرف المسافات البيضاء (بما في ذلك الأسطر الجديدة) داخل المنطقة المذكورة. تتيح لك علامات الاقتباس المزدوجة أيضًا استخدام علامات الاقتباس المفردة العادية التي لا يتم تجاوزها.

حرف النماذج التي تم الخروج منها
@ \@
؟ \?
سطر جديد \n
Tab \t
حرف يونيكود U+XXXX \uXXXX
علامة الاقتباس المفردة (')

أيّ ممّا يلي:

  • \'
  • ضَع السلسلة بأكملها بين علامتَي اقتباس مزدوجتَين ("This'll work"، على سبيل المثال).
علامة الاقتباس المزدوجة (") \"

لاحظ أن إحاطة السلسلة بعلامات اقتباس مفردة لا يعمل.

يحدث تصغير المسافات البيضاء وإنهاء عمل Android بعد تحليل ملف المورد كملف XML. وهذا يعني أنّه يمكن تصغير <string> &#32; &#8200; &#8195;</string> (مسافة، مسافة علامات الترقيم، مسافة Unicode Em) إلى مسافة واحدة (" ")، لأنّها كلها مساحات Unicode بعد تحليل الملف كملف XML. للحفاظ على هذه المساحات كما هي، يمكنك إما اقتباسها (<string>" &#32; &#8200; &#8195;"</string>) أو استخدام رمز الإلغاء في Android (<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%: <big>
  • نص أصغر بنسبة% 20: <صغير>
  • ضبط خصائص الخطوط: <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 باستخدام الكيانات التي تم تخطيها، والتي يتم استردادها بعد ذلك باستخدام fromHtml(String)، بعد حدوث التنسيق. مثلاً:

  1. تخزين المورد النصي ذو النمط كسلسلة HTML تتضمن أحرف إلغاء:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    في هذه السلسلة المنسّقة، تمت إضافة عنصر <b>. لاحظ أنّ القوس الافتتاحي يتضمّن أحرف إلغاء HTML، وذلك باستخدام علامة &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، احرص على تجنّب أي أحرف HTML محتملة في السلاسل التي تستخدمها مع النص المنسَّق باستخدام htmlEncode(String). على سبيل المثال، إذا كنت تُنسِّق سلسلة تحتوي على أحرف مثل "<" أو "&"، يجب تخطّيها قبل التنسيق، بحيث تظهر الأحرف بالشكل الأصلي عند تمرير السلسلة المنسَّقة في 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 هو كائن نصي يمكنك تصميمه باستخدام خصائص الخط الطباعي مثل اللون وسُمك الخط. يمكنك استخدام 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 أيضًا على وظائف الإضافة التي تجعل التعامل مع الامتدادات أسهل. يمكنك الاطّلاع على مستندات حزمة android.text على GitHub للحصول على مزيد من المعلومات.

لمزيد من المعلومات حول استخدام الامتدادات، راجع الروابط التالية:

الأسلوب باستخدام التعليقات التوضيحية

يمكنك تطبيق تصميم معقّد أو مخصّص باستخدام الفئة Annotation مع العلامة <annotation> في ملفات موارد shortcuts.xml. وتتيح لك علامة التعليق التوضيحي وضع علامة على أجزاء من السلسلة لتنسيق مخصّص من خلال تحديد أزواج المفتاح/القيمة المخصّصة في ملف XML الذي يحوّله إطار العمل بعد ذلك إلى مساحات Annotation. يمكنك بعد ذلك استرداد هذه التعليقات التوضيحية واستخدام المفتاح والقيمة لتطبيق النمط.

عند إنشاء تعليقات توضيحية، احرص على إضافة العلامة <annotation> إلى جميع ترجمات السلسلة في كل ملف shortcuts.xml.


تطبيق خط طباعي مخصّص على كلمة "نص" في جميع اللغات

مثال - إضافة خط طباعي مخصص

  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. حمِّل مورد السلسلة وابحث عن التعليقات التوضيحية باستخدام مفتاح الخط. بعد ذلك، يمكنك إنشاء مدى مخصّص واستبدال النطاق الحالي.

    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>، كما هو موضّح في المثال أعلاه، أو في الرمز من خلال إنشاء 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);

لمزيد من المعلومات عن نمط النص، اطّلع على الروابط التالية: