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

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

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

ما مِن سمات.

<string-array>
تحدِّد صفيفًا من السلاسل. تحتوي على عنصر <item> واحد أو أكثر.

:

name
سلسلة: تمثّل هذه السمة اسم الصفيفة. يتم استخدام هذا الاسم كمورد ID للإشارة إلى الصفيفة.
<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، وبالتالي فإن "كتاب واحد" CANNOT TRANSLATE مترجَمة إلى "1 كنيغا" و"101 كتابًا" تمت ترجمتها إلى "101 knyga". فِي هَذِهِ الْأَثْنَاءْ: "كتاب" هو "knyga" و"العديد من الكتب" اسمه "داغ كنيغو" إذا كانت رسالة الجمع باللغة الإنجليزية تحتوي على "كتاب" (مفرد) و"العديد من الكتب" (الجمع) بدون الرقم الفعلي، فيمكن ترجمتها إلى "knyga" (كتاب)/"daug knygü" (العديد من الكتب)، ولكن مع القواعد الليتوانية، ستعرض "knyga" (كتاب واحد)، عندما يكون العدد 101.

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

في الإصدار 24 من واجهة برمجة التطبيقات أو الإصدارات الأحدث، يمكنك استخدام وحدة ICU 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>
حقل مطلوب. يجب أن تكون هذه هي العقدة الجذر.

ما مِن سمات.

<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) يمكن تصغيرها جميعًا إلى مسافة واحدة (" ")، لأنّها كلها مسافات يونيكود بعد تحليل الملف بتنسيق 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> في ملفات موارد schema.xml. تسمح علامة التعليق التوضيحي عليك وضع علامة على أجزاء من السلسلة لتصميم مخصص عن طريق تحديد أزواج المفتاح/القيمة المخصصة في ملف XML الذي يحوّله إطار العمل بعد ذلك إلى امتدادات Annotation. يمكنك بعد ذلك استرداد هذه تعليقات توضيحية واستخدام المفتاح والقيمة لتطبيق النمط.

عند إنشاء تعليقات توضيحية، احرص على إضافة السمة <annotation> لجميع ترجمات السلسلة في كل ملف actions.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. حمِّل مورد السلسلة وابحث عن التعليقات التوضيحية باستخدام مفتاح 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> كما هو موضح في المثال أعلاه، أو في الرمز من خلال إنشاء علامة 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);

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