قد يكون عرض المعلومات النصية هو الجزء الأساسي والأكثر أهمية في العديد من تطبيقات Android. هذه المادة سوف نتحدث عن TextView. كل مطور ، بدءاً من "Hello World" ، يواجه باستمرار عنصر واجهة المستخدم هذا. من وقت لآخر ، عند العمل باستخدام النص ، عليك التفكير في تنفيذ حلول تصميم مختلفة أو تحسين الأداء عند تقديم الشاشة.
سأتحدث عن جهاز TextView وبعض التفاصيل الدقيقة للعمل معه. تم أخذ النصائح الأساسية من تقارير الماضي I / O جوجل.
TextView تحت غطاء محرك السيارة
لتقديم النص في Android ، يتم استخدام مجموعة كاملة من المكتبات المختلفة أسفل الغطاء. يمكن تقسيمها إلى قسمين رئيسيين - كود جافا ورمز أصلي:
يعد Java code جزءًا أساسيًا من Android SDK المتاح لمطوري التطبيقات ، ويمكن نقل الميزات الجديدة منه إلى مكتبة الدعم.
تتم كتابة TextView الأساسية نفسها في C ++ ، مما يحد من النقل إلى مكتبة دعم الميزات الجديدة المطبقة هناك من الإصدارات الجديدة من نظام التشغيل. الأساسية هي المكتبات التالية:
- Minikin يستخدم لقياس طول النص وفواصل الأسطر والكلمات بواسطة المقاطع.
- يوفر ICU دعم Unicode.
- يبحث HarfBuzz عن أحرف Unicode عن عناصر الرسوم (الحروف الرسومية) المقابلة في الخطوط.
- FreeType يجعل الصور النقطية من الحروف الرسومية.
- Skia هو محرك لرسم الرسومات ثنائية الأبعاد.
قياس طول النص وفواصل الأسطر
إذا قمت بتمرير السطر إلى مكتبة Minikin ، والتي يتم استخدامها داخل TextView ، فإن أول ما تحدده هو ما هي الحروف الرسومية التي يتكون منها السطر:
كما ترون من هذا المثال ، فإن مطابقة أحرف Unicode مع الحروف الرسومية لن يكون دائمًا واحدًا إلى واحد: هنا 3 أحرف في وقت واحد ستتوافق مع حرف ffi واحد. بالإضافة إلى ذلك ، يجدر الانتباه إلى أنه يمكن العثور على الحروف الرسومية اللازمة في خطوط النظام المختلفة.
يمكن أن يؤدي العثور على الحروف الرسومية فقط في خطوط النظام إلى صعوبات ، خاصةً إذا كانت الرموز أو الرموز التعبيرية معروضة من خلال أحرف ، ومن المفترض أن تجمع الأحرف من خطوط مختلفة في سطر واحد. لذلك ، بدءًا من Android Q (29) ، أصبح من الممكن إنشاء قائمة الخطوط الخاصة بك التي تأتي مع التطبيق. سيتم استخدام هذه القائمة للبحث عن الحروف الرسومية:
textView.typeface = TypeFace.CustomFallbackBuilder( FontFamily.Builder( Font.Builder(assets, “lato.ttf”).build() ).build() ).addCustomFallback( FontFamily.Builder( Font.Builder(assets, “kosugi.ttf”).build() ).build() ).build()
الآن ، باستخدام CustomFallbackBuilder
عند مطابقة الأحرف مع الحروف الرسومية ، سيتم CustomFallbackBuilder
SDK عبر عائلة الخطوط المحددة بالترتيب ، وإذا تعذر العثور عليه ، فسيستمر البحث في خطوط النظام (ومن خلال طريقة setSystemFallback()
يمكنك تحديد عائلة خطوط النظام المفضلة). يحتوي CustomFallbackBuilder
على حد أقصى لعدد عائلة الخطوط - لا يمكنك إضافة أكثر من 64 خطًا.
مكتبة Minikin يقسم السلاسل إلى كلمات ويقيس الكلمات الفردية. لتسريع العمل ، بدءًا من Lollipop (21) ، يتم استخدام ذاكرة التخزين المؤقت لنظام الكلمات من LRU . تعطي ذاكرة التخزين المؤقت هذه مكسبًا كبيرًا للأداء: Paint.measureText()
مكالمة Paint.measureText()
للكلمة المخزنة مؤقتًا 3٪ في المتوسط من الوقت الذي يتم فيه حساب حجمها لأول مرة.
إذا كان النص لا يناسب العرض المحدد ، يقوم Minikin بترتيب فواصل الأسطر والكلمات في النص. بدءًا من Marshmallow (23) ، يمكنك التحكم في سلوكه عن طريق تحديد السمات الخاصة لـ BreakView و hyphenationFrequency
الخاصة بـ TextView.
باستخدام القيمة breakStrategy=simple
المكتبة ببساطة بترتيب الواصلات بالتتابع ، مروراً بالنص: بمجرد توقف السطر عن الملاءمة ، يتم وضع الواصلة قبل الكلمة الأخيرة.
في القيمة balanced
ستحاول المكتبة جعل فواصل الأسطر بحيث يتم محاذاة الخطوط في العرض.
لدى high_quality
نفس السلوك balanced
، باستثناء بعض الاختلافات (أحدها: في السطر ما قبل الأخير ، يمكن أن يكون الواصلة عبارة عن كلمات منفصلة فقط ، ولكن أيضًا كلمات بواسطة المقاطع).
تسمح hyphenationFrequency
السمة hyphenationFrequency
بالتحكم في إستراتيجية التفاف الكلمات عن طريق المقاطع. قيمة none
لن تفعل الواصلة التلقائية ، normal
سيجعل تردد صغير من الواصلة ، full
، وبالتالي ، سوف تستخدم الحد الأقصى لعدد الكلمات.
أداء تقديم النص حسب الإشارات المحددة (تقاس على Android P (28) ):
نظرًا لوجود أداء قوي إلى حد ما ، قرر مطورو Google ، بدءًا من الإصدار Q (29) و AppCompat 1.1.0 ، إيقاف تشغيل الواصلة افتراضيًا. إذا كانت ميزة التفاف الكلمات مهمة في التطبيق ، فأنت بحاجة الآن إلى تمكينها بشكل صريح.
عند استخدام التفاف الكلمات ، يجب أن يأخذ المرء في الاعتبار أن اللغة المحددة الحالية في نظام التشغيل ستؤثر على تشغيل المكتبة. اعتمادًا على اللغة ، سيختار النظام قواميس خاصة بها قواعد نقل.
أنماط النص
هناك عدة طرق لنمط النص في Android:
- نمط مفرد ينطبق على عنصر TextView بأكمله.
- متعدد النمط (متعدد النمط) - عدة أنماط في وقت واحد ، والتي يمكن تطبيقها على النص ، على مستوى الفقرة أو الأحرف الفردية. هناك عدة طرق للقيام بذلك:
- رسم النص على قماش
- علامات HTML
- عناصر العلامات الخاصة - تمتد
يتضمن النمط الفردي استخدام أنماط XML أو سمات XML في علامة تمييز النص. في هذه الحالة ، سيقوم النظام بتطبيق القيم من الموارد بالترتيب التالي: TextAppearance ، السمة (السمة) ، النمط الافتراضي (النمط الافتراضي) ، النمط من التطبيق ، والأولوية القصوى هي قيم سمات العرض.
يعد استخدام الموارد حلاً بسيطًا إلى حد ما ، لكن لسوء الحظ ، لا يسمح لك بتطبيق النمط على أجزاء من النص.
تعد علامات HTML حلًا بسيطًا آخر يوفر ميزات مثل جعل الكلمات الفردية بالخط العريض أو المائل أو حتى تسليط الضوء على النقاط التي تحتوي على نقاط في النص. جميع احتياجات المطور هي إجراء مكالمة إلى طريقة Html.fromHtml()
، والتي ستحول النص الذي تم وضع علامة عليه إلى نص تم Html.fromHtml()
عبر Html.fromHtml()
. لكن هذا الحل له قدرات محدودة ، لأنه يتعرف على جزء فقط من علامات html ولا يدعم أنماط CSS.
val text = "My text <ul><li>bullet one</li><li>bullet two</li></ul>" myTextView.text = Html.fromHtml(text)
يمكن دمج طرق مختلفة لتصميم النص ، ولكن يجدر تذكر أولوية طريقة معينة ، والتي سوف تؤثر على النتيجة النهائية:
هناك طريقة أخرى - رسم النص على القماش - تمنح المطور التحكم الكامل في إخراج النص: على سبيل المثال ، يمكنك رسم النص على طول خط منحني. لكن مثل هذا الحل ، وفقًا للمتطلبات ، قد يكون من الصعب تطبيقه ويتجاوز نطاق هذا المقال.
القناطر
يستخدم TextView مسافات لضبط الأنماط. باستخدام المسافات ، يمكنك تغيير لون مجموعة من الأحرف ، وجعل جزء من النص كروابط ، وتغيير حجم النص ، ورسم نقطة أمام فقرة ، وما إلى ذلك.
يمكن تمييز الفئات التالية من المسافات:
- امتدادات الأحرف - يتم تطبيقها على مستوى حرف السلسلة.
- تؤثر على المظهر - لا تقم بتغيير حجم النص.
- التأثير المتري - تغيير حجم النص.
- يمتد فقرة - تطبق على مستوى الفقرة.
يحتوي إطار عمل Android على واجهات وفئات تجريدية مع أساليب يتم استدعاؤها أثناء onMeasure()
وعرض TextView ، وتمنح هذه الطرق spans الوصول إلى الكائنات ذات المستوى الأدنى مثل TextPaint
و Canvas
. باستخدام span ، يتحقق إطار عمل Android من واجهات هذا الكائن التي تطبقها لاستدعاء الأساليب الضرورية.
يحدد إطار عمل Android حوالي 20+ تمددًا ، لذا فمن الأفضل قبل التحقق من ملائمة SDK.
المظهر مقابل المتري المؤثر على المسافات
تؤثر الفئة الأولى من المسافات على كيفية ظهور الأحرف في السلسلة: لون الحرف أو لون الخلفية أو أحرف تحتها خط أو شطبها ، إلخ. تقوم هذه UpdateAppearance
واجهة UpdateAppearance
وترث من فئة CharacterStyle
، والتي توفر الوصول إلى كائن TextPaint
.
يؤثر تأثير القياس المتري على حجم النص والتخطيط ، لذلك ، لا يتطلب استخدام هذا النطاق إعادة رسم TextView فحسب ، بل يتطلب أيضًا استدعاء onMeasure()
/ onLayout()
. عادةً ما يتم توريث هذه MetricAffectingSpan
فئة MetricAffectingSpan
، التي ترث من CharacterStyle
المذكور أعلاه.
حرف مقابل الفقرة التي تؤثر على يمتد
يؤثر امتداد الفقرة على مجموعة كاملة من النص: يمكنه تغيير المحاذاة ، المسافة البادئة ، أو حتى إدراج نقطة في بداية الفقرة. يجب أن يتم توريث هذه المسافات من فئة ParagraphStyle
وإدراجها في النص من بداية الفقرة بالضبط إلى نهايتها. إذا كان النطاق غير صحيح ، فلن يعمل النطاق.
على Android ، تعتبر الفقرات جزءًا من النص مفصولة بخطوط جديدة ( \n
).
الكتابة الخاصة بك يمتد
عند كتابة المسافات الخاصة بك ، عليك أن تقرر ما الذي ستؤثر عليه الفترة الزمنية من أجل اختيار الفئة التي ترث منها:
- يؤثر النص على مستوى الحرف ->
CharacterStyle
- يؤثر النص على مستوى الفقرة ->
ParagraphStyle
- يؤثر على عرض النص →
UpdateAppearance
- يؤثر على حجم النص -
UpdateLayout
فيما يلي مثال على مدى لتغيير الخط:
class CustomTypefaceSpan(private val font: Typeface?) : MetricAffectingSpan() { override fun updateMeasureState(textPaint: TextPaint) = update(textPaint) override fun updateDrawState(textPaint: TextPaint) = update(textPaint) fun update(textPaint: TextPaint) { textPaint.apply { val old = typeface val oldStyle = old?.style ?: 0 val font = Typeface.create(font, oldStyle) typeface = font
تخيل أننا نرغب في إنشاء امتداد خاص بنا لتسليط الضوء على كتل الشفرة ، لذلك سنقوم بتحرير امتدادنا السابق - بعد إضافة الخط ، سنضيف أيضًا تغييرًا في لون خلفية النص:
class CodeBlockSpan(private val font: Typeface?) : MetricAffectingSpan() { … fun update(textPaint: TextPaint) { textPaint.apply {
تطبيق تمتد على النص:
ولكن يمكنك الحصول على نفس النتيجة تمامًا من خلال الجمع بين منطقتين: أخذ CustomTypefaceSpan
و BackgroundColorSpan
CustomTypefaceSpan
من إطار عمل Android:
سيكون لهذين الحلين فرق. والحقيقة هي أن Parcelable
المكتوبة ذاتيا لا يمكنها تنفيذ واجهة Parcelable
، على عكس تلك الخاصة بالنظام.
عند إرسال خط منمق من خلال Intent أو الحافظة في حالة وجود فترة من العلامات المكتوبة ذاتيًا ، لن يتم حفظها. عند استخدام المسافات من الإطار ، ستبقى العلامات.
باستخدام يمتد في النص
هناك واجهات اثنين للنص المنمق في الإطار: Spannable
و Spannable
(مع Spannable
بدون تغيير Spannable
للتغيير ، على التوالي) وثلاثة تطبيقات: SpannedString
(نص غير متغير) ، SpannableString
(نص غير متغير) و SpannableStringBuilder
(نص قابل للتغيير).
على سبيل المثال ، يتم استخدام EditText
داخل EditText
الذي يحتاج إلى تغيير النص.
يمكنك إضافة فترة جديدة إلى خط باستخدام الطريقة:
setSpan(Object what, int start, int end, int flags)
يتم تمرير المدى خلال المعلمة الأولى ، ثم تتم الإشارة إلى نطاق المؤشرات في النص. ويمكن التحكم في المعلمة الأخيرة ، ما هو سلوك المدى عند إدراج نص جديد: ما إذا كان سيتم تمديد الامتداد إلى النص الذي تم إدراجه في نقطة البداية أو النهاية (إذا قمت بإدراج نص جديد في المنتصف ، فسيتم تطبيق الامتداد تلقائيًا عليه ، بغض النظر عن قيم العلامة) .
تختلف الفئات المذكورة أعلاه ليس فقط من حيث الدلالة ، ولكن أيضًا في كيفية ترتيبها داخليًا: SpannedString
و SpannableString
صفيفين لتخزين SpannableStringBuilder
، ويستخدم SpannableStringBuilder
شجرة فاصل .
إذا أجريت اختبارات لسرعة تقديم النص اعتمادًا على عدد المسافات ، فستحصل على النتائج التالية: عند استخدام ما يصل إلى 250 مساحة تقريبًا على التوالي ، SpannableString
و SpannableStringBuilder
بنفس السرعة تقريبًا ، ولكن إذا أصبحت عناصر العلامات أكثر من 250 ، SpannableString
تبدأ SpannableString
ليخسره. وبالتالي ، إذا كانت المهمة تتمثل في تطبيق نمط على بعض النص ، فعند اختيار فئة ، يجب أن يسترشد الفرد بمتطلبات الدلالة: ما إذا كان الخط والأنماط سيكونان قابلاً للتغيير. ولكن إذا تطلب الترميز أكثر من 250 SpannableStringBuilder
، فيجب عليك دائمًا منح SpannableStringBuilder
لـ SpannableStringBuilder
.
التحقق من مدى في النص
تنشأ المهمة بشكل دوري للتحقق مما إذا كان للخط الممتد نطاق معين. وعلى Stackoverflow يمكنك العثور على هذا الرمز:
fun <T> hasSpan(spanned: Spanned, clazz: Class<T>): Boolean { val spans: Array<out T> = spanned.getSpans(0, spanned.length, clazz) return spans.isNotEmpty() }
سيعمل هذا الحل ، لكنه غير فعال: يجب عليك متابعة كافة المسافات ، والتحقق مما إذا كان كل واحد منهم ينتمي إلى النوع الذي تم تمريره ، وجمع النتيجة في صفيف ، وفي النهاية تحقق فقط من أن الصفيف غير فارغ.
سيكون الحل الأكثر فعالية هو استخدام الأسلوب nextSpanTransition()
:
fun <T> hasSpan(spanned: Spanned, clazz: Class<T>): Boolean { val limit = spanned.length return spanned.nextSpanTransition(0, limit, clazz) < limit }
ترميز النص في الموارد اللغوية المختلفة
قد تنشأ مثل هذه المهمة عندما يكون مطلوبًا تسليط الضوء على كلمة معينة باستخدام العلامات في مختلف موارد السلسلة. على سبيل المثال ، نحتاج إلى إبراز كلمة "text" في النسخة الإنجليزية و "texto" باللغة الإسبانية:
<string name="title">Best practices for text in Android</string> <string name=”title”>Texto en Android: mejores prácticas</string>
إذا كنت بحاجة إلى شيء بسيط ، على سبيل المثال ، لتمييز الكلمة بالخط العريض ، فيمكنك استخدام علامات html المعتادة ( <b>
). في واجهة المستخدم ، تحتاج فقط إلى تعيين مورد السلسلة في TextView:
textView.setText(R.string.title)
ولكن إذا كنت بحاجة إلى شيء أكثر تعقيدًا ، على سبيل المثال ، تغيير الخط ، فلن يمكن استخدام html بعد الآن. يكمن الحل في استخدام <annotation>
. تسمح لك هذه العلامة بتحديد أي زوج من مفاتيح القيمة في ملف xml. عندما نقوم بسحب سلسلة من الموارد ، يتم تحويل هذه العلامات تلقائيًا إلى Annotation
، مرتبة في النص باستخدام المفاتيح والقيم المقابلة. بعد ذلك ، يمكنك تحليل قائمة التعليقات التوضيحية في النص وتطبيق المسافات اللازمة.
لنفترض أننا بحاجة إلى تغيير الخط باستخدام CustomTypefaceSpan
.
أضف علامة وتعريف مفتاح "الخط" له وقيمة - نوع الخط الذي نريد استخدامه هو "title_emphasis" :
<string name="title">Best practices for <annotation font=”title_emphasis”>text</annotation> in Android</string> <string name=”title”><annotation font=”title_emphasis”>Texto</annotation> en Android: mejores prácticas</string>
اسحب السلسلة من الموارد ، وابحث عن التعليقات التوضيحية باستخدام مفتاح "الخط" وترتيب المسافات:
تم ذكره أعلاه أن Parcelable
من خارج إطار Android لا يمكنها تنفيذ Parcelable
ويتم نقلها عبر Intent. لكن هذا لا ينطبق على التعليقات التوضيحية التي تنفذ Parcelable
. حتى تتمكن من تمرير السلسلة المشروحة عبر Intent والتحليل بالطريقة نفسها تمامًا عن طريق ترتيب امتداداتك.
كيف يتم وضع النص في TextView
TextView يمكن عرض النص ليس فقط ، ولكن أيضا الصور. يمكنك أيضًا تعيين مسافات بادئة مختلفة أمام النص. تحت الغطاء ، يعمل هذا حتى يقوم TextView بإنشاء فئة فرعية ، Layout ، وهي مسؤولة مباشرةً عن عرض النص. هذه فئة تجريدية تحتوي على ثلاثة تطبيقات ؛ عادةً ما لا يتعين عليك العمل معهم مباشرة ما لم تكتب التحكم الخاص بك:
- BoringLayout يستخدم للنصوص البسيطة ، لا يدعم فواصل الأسطر ، RTL وأشياء أخرى ، لكنه الأكثر وزنًا. يستخدم TextView إذا كان النص يلبي جميع القيود.
- يتم استخدام StaticLayout في TextView لحالات أخرى.
- يتم استخدام DynamicLayout للنص القابل للتغيير في تحرير النص.
يحتوي Layout على العديد من الأساليب التي تتيح لك معرفة المعلمات المختلفة للنص المعروض: إحداثيات الأسطر ، الأساس ، إحداثيات بداية ونهاية النص في السطر ، إلخ. (يمكن الاطلاع على مزيد من التفاصيل في الوثائق )
هذه الأساليب يمكن أن تكون مفيدة جدا. على سبيل المثال ، يواجه بعض المطورين مهمة استخراج جزء من النص إلى مستطيلات مستديرة ، ومحاولة إيجاد حل له من خلال مسافات غير قابلة للتطبيق في حل هذه المشكلة.
لكن أساليب الطبقة Layout يمكن أن تنقذ. هنا حل عينة:
باستخدام التعليقات التوضيحية ، نختار الكلمات التي يجب أن تكون محاطة بدائرة في المستطيلات.
ثم قم بإنشاء 4 موارد قابلة للتطبيق لجميع حالات التفاف النص ، والتي يجب تضمينها في المستطيلات:
بعد ذلك ، نجد التعليقات التوضيحية التي نحتاجها في النص ، كما هو موضح أعلاه. الآن لدينا فهارس بداية ونهاية هذا التعليق التوضيحي. من خلال أساليب Layout ، يمكنك معرفة رقم السطر الذي يبدأ عليه النص المشروح ، والذي ينتهي به:
val startLine = layout.getLineForOffset(spanStartIndex) val endLine = layout.getLineForOffset(spanEndIndex)
بعد ذلك ، يجب عليك رسم مستطيل واحد أو أكثر. فكر في الحالة البسيطة عندما ظهر الجزء المشروح من النص في سطر واحد ، ثم نحتاج إلى مستطيل واحد فقط بأربع زوايا مدورة. حدد إحداثياتها وارسم:
... if (startLine == endLine) { val lineTop = layout.getLineTop(startLine)
كما ترى من هذا المثال ، يخزن Layout الكثير من المعلومات المفيدة على النص المعروض ، مما يساعد في تنفيذ العديد من المهام غير القياسية.
TextView الأداء
يتم عرض TextView ، مثل أي طريقة عرض ، عبر ثلاث مراحل عند عرضها: onMeasure()
و onLayout()
و onDraw()
. في الوقت نفسه ، يأخذ onMeasure()
معظم الوقت ، على عكس الطريقتين الأخريين: في هذه اللحظة ، يتم إعادة إنشاء فئة التخطيط ويتم حساب حجم النص. لذا فإن تغيير حجم النص (على سبيل المثال ، تغيير الخط) يستلزم الكثير من العمل. سيكون تغيير لون النص أكثر وضوحًا لأنه يتطلب فقط استدعاء onDraw()
. كما ذكر أعلاه ، يحتوي النظام على ذاكرة التخزين المؤقت للكلمات العالمية مع أحجام محسوبة. إذا كانت الكلمة موجودة بالفعل في ذاكرة التخزين المؤقت ، فإن استدعاء onMeasure()
لأنه سيستغرق 11-16٪ من الوقت اللازم لإجراء عملية حسابية كاملة.
تسريع النص
في عام 2015 ، قام مطورو Instagram بتسريع عرض التعليقات على الصور باستخدام ذاكرة التخزين المؤقت العالمية. كانت الفكرة هي رسم النص تقريبًا قبل عرضه على الشاشة ، وبالتالي "تسخين" ذاكرة التخزين المؤقت للنظام. عندما حان الوقت لإظهار النص ، رأى المستخدم ذلك بشكل أسرع ، حيث تم قياس النص بالفعل وكان في ذاكرة التخزين المؤقت.
بدءًا من Android P (28) ، أضاف مطورو Google إلى واجهة برمجة التطبيقات (API) القدرة على تنفيذ مرحلة قياس حجم النص مقدمًا في مؤشر ترابط الخلفية - PrecomputedText
( PrecomputedText
لـ API الذي يبدأ بـ Android I (14) - PrecomputedTextCompat
). باستخدام واجهة برمجة التطبيقات الجديدة ، سيتم إنجاز 90٪ من العمل في سلسلة رسائل الخلفية.
مثال:
عرض نص كبير
إذا كنت بحاجة إلى إظهار نص كبير ، فلا تقم بنقله على الفور إلى TextView. وإلا ، فقد يتوقف التطبيق عن العمل بسلاسة أو تجميد تام ، حيث إنه سوف يقوم بالكثير من العمل في سلسلة الرسائل الرئيسية لإظهار نص ضخم قد لا ينتقل إليه المستخدم حتى النهاية. يتمثل الحل في تقسيم النص إلى أجزاء (مثل الفقرات) وعرض الأجزاء الفردية في RecyclerView. لتسريع أكبر ، يمكنك حساب حجم كتل النص مسبقًا باستخدام PrecomputedText.
لتسهيل تضمين PrecomputedText في RecyclerView ، ابتكر مطورو Google أساليب خاصة لـ PrecomputedTextCompat.getTextFuture()
و AppCompatTextView.setTextFuture()
:
fun onBindViewHolder(vh: ViewHolder, position: Int) { val data = getData(position) vh.textView.setTextSize(...) vh.textView.setFontVariationSettings(...)
RecyclerView , , , .
, getTextFuture()
(, ), , , getTextFuture()
, , TextView.
, TextView
TextView.setText()
:
if (type == SPANNABLE || movementMethod != null) { text = spannableFactory.newSpannable(spannable)
span' TextView, setText()
, .
, . TextView , -, . , . , , TextView spannableFactory
:
class MySpannableFactory : Spannable.Factory() { override fun newSpannable(source: CharSequence): Spannable { return source as? Spannable ?: super.newSpannable(source) } } textView.spannableFactory = MySpannableFactory()
textView.setText(spannable, BufferType.SPANNABLE)
, .
Google span' RecyclerView, .
TextView, span, setText()
. TextView span. TextView spannable- span', :
val spannable = textView.getText() as Spannable val span = CustomTypefaceSpan(span) spannable.setSpan(span, ...)
span, TextView, TextView . , invalidate()
, – requestLayout()
:
val spannable = textView.getText() as Spannable val span = CustomTypefaceSpan(span) spannable.setSpan(span, ...) span.setTypeface(anotherTypeface) textView.requestLayout()
autoLink
TextView . autoLink
. autoLink=”web”
TextView URL URLSpan
. , SDK setText()
:
spannable = new SpannableString(string); Matcher m = pattern.matcher(text); while (...) {
UI , autoLink=”web”
RecyclerView. . LinkifyCompat
:
autoLink
map
– ( all
). . , WebView, ! SDK Linkify.gatherMapLinks()
, :
while ((address = WebView.findAddress(string)) != null) { ... }
WebView TODO SDK:
public static String findAddress(String addr) {
? Smart Linkify, Android P (28) , , . :
Linkify, . toolbar , Google .
Smart Linkify : , .
Magnifier
Android P (28) , – Magnifier, . .
TextView, EditText WebView, : API .
استنتاج
Android , , :
- , Google I/O'19 “Best Practices for Using Text in Android” .
روابط مفيدة
مقالات
تقارير