Spans اشیاء نشانه گذاری قدرتمندی هستند که می توانید از آنها برای استایل دادن به متن در سطح کاراکتر یا پاراگراف استفاده کنید. با پیوست کردن دهانه به اشیاء متن، میتوانید متن را به روشهای مختلفی تغییر دهید، از جمله افزودن رنگ، قابل کلیک کردن متن، مقیاسگذاری اندازه متن و کشیدن متن به روشی سفارشی. Spans همچنین می تواند ویژگی های TextPaint
را تغییر دهد، روی Canvas
بکشد، و طرح بندی متن را تغییر دهد.
اندروید انواع مختلفی از دهانه ها را ارائه می دهد که انواع الگوهای متداول یک ظاهر طراحی متن را پوشش می دهد. شما همچنین می توانید دهانه های خود را برای اعمال یک ظاهر طراحی سفارشی ایجاد کنید.
یک فاصله ایجاد و اعمال کنید
برای ایجاد span می توانید از یکی از کلاس های فهرست شده در جدول زیر استفاده کنید. کلاس ها بر اساس اینکه آیا خود متن قابل تغییر است، آیا نشانه گذاری متن قابل تغییر است یا نه، و اینکه چه ساختار داده زیربنایی حاوی داده های دهانه است، متفاوت است.
کلاس | متن قابل تغییر | نشانه گذاری قابل تغییر | ساختار داده |
---|---|---|---|
SpannedString | خیر | خیر | آرایه خطی |
SpannableString | خیر | بله | آرایه خطی |
SpannableStringBuilder | بله | بله | درخت فاصله |
هر سه کلاس رابط Spanned
را گسترش می دهند. SpannableString
و SpannableStringBuilder
همچنین رابط Spannable
را گسترش می دهند.
در اینجا نحوه تصمیم گیری برای استفاده از آن آمده است:
- اگر بعد از ایجاد متن یا نشانه گذاری را تغییر نمی دهید، از
SpannedString
استفاده کنید. - اگر نیاز دارید تعداد کمی از دهانه ها را به یک شیء متنی وصل کنید و خود متن فقط خواندنی است، از
SpannableString
استفاده کنید. - اگر بعد از ایجاد نیاز به تغییر متن دارید و باید span ها را به متن ضمیمه کنید، از
SpannableStringBuilder
استفاده کنید. - اگر نیاز به پیوستن تعداد زیادی دهانه به یک شیء متنی دارید، صرف نظر از اینکه خود متن فقط خواندنی است یا خیر، از
SpannableStringBuilder
استفاده کنید.
برای اعمال یک span، setSpan(Object _what_, int _start_, int _end_, int _flags_)
روی یک شیء Spannable
فراخوانی کنید. پارامتر what به دامنهای که روی متن اعمال میکنید، و پارامترهای شروع و پایان نشاندهنده قسمتی از متن است که در حال اعمال دامنه روی آن هستید.
اگر متنی را در داخل مرزهای یک دهانه درج کنید، دامنه به طور خودکار گسترش می یابد تا متن درج شده را نیز شامل شود. هنگام درج متن در مرزهای دهانه - یعنی در شاخص های شروع یا پایان - پارامتر flags تعیین می کند که آیا دامنه گسترش می یابد تا متن درج شده را در بر بگیرد یا خیر. از پرچم Spannable.SPAN_EXCLUSIVE_INCLUSIVE
برای اضافه کردن متن درج شده استفاده کنید و از Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
برای حذف متن درج شده استفاده کنید.
مثال زیر نحوه اتصال ForegroundColorSpan
به یک رشته نشان می دهد:
کاتلین
val spannable = SpannableStringBuilder("Text is spantastic!") spannable.setSpan( ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE )
جاوا
SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE );
از آنجایی که دامنه با استفاده از Spannable.SPAN_EXCLUSIVE_INCLUSIVE
تنظیم میشود.SPAN_EXCLUSIVE_INCLUSIVE، دامنه گسترش مییابد تا متن درج شده در مرزهای دهانه را در بر بگیرد، همانطور که در مثال زیر نشان داده شده است:
کاتلین
val spannable = SpannableStringBuilder("Text is spantastic!") spannable.setSpan( ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE ) spannable.insert(12, "(& fon)")
جاوا
SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE ); spannable.insert(12, "(& fon)");
می توانید چندین دهانه را به یک متن متصل کنید. مثال زیر نحوه ایجاد متنی پررنگ و قرمز را نشان می دهد:
کاتلین
val spannable = SpannableString("Text is spantastic!") spannable.setSpan(ForegroundColorSpan(Color.RED), 8, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) spannable.setSpan( StyleSpan(Typeface.BOLD), 8, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE )
جاوا
SpannableString spannable = new SpannableString("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ); spannable.setSpan( new StyleSpan(Typeface.BOLD), 8, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
انواع دامنه اندروید
Android بیش از 20 نوع span را در بسته android.text.style ارائه می دهد. اندروید دهانه ها را به دو روش اصلی دسته بندی می کند:
- چگونه دامنه بر متن تأثیر می گذارد: یک بازه می تواند بر ظاهر متن یا معیارهای متن تأثیر بگذارد.
- دامنه گستره: برخی از دهانه ها را می توان برای شخصیت های فردی اعمال کرد، در حالی که برخی دیگر باید برای کل پاراگراف اعمال شوند.
بخش های بعدی این دسته بندی ها را با جزئیات بیشتری توضیح می دهند.
گستره هایی که بر ظاهر متن تأثیر می گذارد
برخی از گسترههایی که در سطح کاراکتر اعمال میشوند، بر ظاهر متن تأثیر میگذارند، مانند تغییر متن یا رنگ پسزمینه و اضافه کردن خطهای خطدار یا خط خطی. این گستره ها کلاس CharacterStyle
را گسترش می دهند.
مثال کد زیر نحوه اعمال UnderlineSpan
برای خط کشیدن زیر متن نشان می دهد:
کاتلین
val string = SpannableString("Text with underline span") string.setSpan(UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
جاوا
SpannableString string = new SpannableString("Text with underline span"); string.setSpan(new UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
گستره هایی که فقط بر ظاهر متن تأثیر می گذارند، باعث ترسیم مجدد متن می شوند بدون اینکه باعث محاسبه مجدد طرح بندی شوند. این گستره ها UpdateAppearance
پیاده سازی کرده و CharacterStyle
گسترش می دهند. زیر کلاس های CharacterStyle
نحوه رسم متن را با فراهم کردن دسترسی برای به روز رسانی TextPaint
تعریف می کنند.
گستره هایی که بر معیارهای متن تأثیر می گذارد
گسترههای دیگری که در سطح کاراکتر اعمال میشوند بر معیارهای متن تأثیر میگذارند، مانند ارتفاع خط و اندازه متن. این گستره ها کلاس MetricAffectingSpan
را گسترش می دهند.
مثال کد زیر یک RelativeSizeSpan
ایجاد می کند که اندازه متن را 50٪ افزایش می دهد:
کاتلین
val string = SpannableString("Text with relative size span") string.setSpan(RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
جاوا
SpannableString string = new SpannableString("Text with relative size span"); string.setSpan(new RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
اعمال یک گستره که بر معیارهای متن تأثیر میگذارد باعث میشود یک شی مشاهدهکننده دوباره متن را برای چیدمان و رندر صحیح اندازهگیری کند - برای مثال، تغییر اندازه متن ممکن است باعث شود کلمات در خطوط مختلف ظاهر شوند. اعمال فاصله قبلی باعث اندازه گیری مجدد، محاسبه مجدد طرح بندی متن و ترسیم مجدد متن می شود.
گستره هایی که بر متریک های متن تأثیر می گذارند، کلاس MetricAffectingSpan
را گسترش می دهند، یک کلاس انتزاعی که به زیرکلاس ها اجازه می دهد با فراهم کردن دسترسی به TextPaint
، نحوه تأثیرگذاری دامنه بر اندازه گیری متن را تعریف کنند. از آنجایی که MetricAffectingSpan
CharacterSpan
گسترش می دهد، کلاس های فرعی بر ظاهر متن در سطح کاراکتر تأثیر می گذارند.
گستره هایی که بر پاراگراف ها تأثیر می گذارد
یک بازه همچنین می تواند بر روی متن در سطح پاراگراف تأثیر بگذارد، مانند تغییر تراز یا حاشیه یک بلوک متن. گستره هایی که کل پاراگراف ها را تحت تأثیر قرار می دهند، ParagraphStyle
پیاده سازی می کنند. برای استفاده از این دهانهها، آنها را به کل پاراگراف متصل میکنید، به استثنای کاراکتر خط جدید پایانی. اگر بخواهید یک پاراگراف را به چیزی غیر از یک پاراگراف کامل اعمال کنید، اندروید به هیچ وجه این دامنه را اعمال نمی کند.
شکل 8 نشان می دهد که اندروید چگونه پاراگراف ها را در متن جدا می کند.
مثال کد زیر یک QuoteSpan
را برای یک پاراگراف اعمال می کند. توجه داشته باشید که اگر دهانه را به موقعیتی غیر از ابتدا یا انتهای یک پاراگراف وصل کنید، اندروید به هیچ وجه این سبک را اعمال نمی کند.
کاتلین
spannable.setSpan(QuoteSpan(color), 8, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
جاوا
spannable.setSpan(new QuoteSpan(color), 8, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ایجاد دهانه های سفارشی
اگر به عملکردی بیشتر از آنچه در گستره اندروید موجود ارائه شده نیاز دارید، می توانید یک span سفارشی پیاده سازی کنید. هنگام پیاده سازی دامنه خود، تصمیم بگیرید که آیا دامنه شما بر روی متن در سطح کاراکتر یا سطح پاراگراف تأثیر می گذارد و همچنین بر روی طرح یا ظاهر متن تأثیر می گذارد. این به شما کمک می کند تا تعیین کنید کدام کلاس های پایه را می توانید گسترش دهید و چه رابط هایی را ممکن است نیاز به پیاده سازی داشته باشید. برای مرجع از جدول زیر استفاده کنید:
سناریو | کلاس یا رابط |
---|---|
دامنه شما روی متن در سطح کاراکتر تأثیر می گذارد. | CharacterStyle |
دامنه شما بر ظاهر متن تأثیر می گذارد. | UpdateAppearance |
دامنه شما بر معیارهای متن تأثیر می گذارد. | UpdateLayout |
دامنه شما بر روی متن در سطح پاراگراف تأثیر می گذارد. | ParagraphStyle |
برای مثال، اگر نیاز به پیادهسازی یک دامنه سفارشی دارید که اندازه و رنگ متن را تغییر میدهد، RelativeSizeSpan
گسترش دهید. از طریق وراثت، RelativeSizeSpan
CharacterStyle
گسترش داده و دو رابط Update
را پیاده سازی می کند. از آنجایی که این کلاس قبلاً برای updateDrawState
و updateMeasureState
تماسهای بک ارائه میدهد، میتوانید برای پیادهسازی رفتار سفارشی خود، این تماسها را لغو کنید. کد زیر یک دامنه سفارشی ایجاد می کند که RelativeSizeSpan
را گسترش می دهد و برای تنظیم رنگ TextPaint
، callback updateDrawState
را لغو می کند:
کاتلین
class RelativeSizeColorSpan( size: Float, @ColorInt private val color: Int ) : RelativeSizeSpan(size) { override fun updateDrawState(textPaint: TextPaint) { super.updateDrawState(textPaint) textPaint.color = color } }
جاوا
public class RelativeSizeColorSpan extends RelativeSizeSpan { private int color; public RelativeSizeColorSpan(float spanSize, int spanColor) { super(spanSize); color = spanColor; } @Override public void updateDrawState(TextPaint textPaint) { super.updateDrawState(textPaint); textPaint.setColor(color); } }
این مثال نحوه ایجاد یک بازه سفارشی را نشان می دهد. شما می توانید با اعمال یک RelativeSizeSpan
و ForegroundColorSpan
روی متن به همان جلوه دست پیدا کنید.
استفاده از بازه آزمایشی
رابط Spanned
به شما این امکان را می دهد که هم بازه ها را تنظیم کنید و هم گستره ها را از متن بازیابی کنید. هنگام آزمایش، یک تست Android JUnit را اجرا کنید تا بررسی کنید که دهانههای صحیح در مکانهای صحیح اضافه شدهاند. برنامه نمونه Text Styling شامل یک بازه است که با پیوست کردن BulletPointSpan
به متن، نشانه گذاری را روی نقاط گلوله اعمال می کند. مثال کد زیر نشان می دهد که چگونه می توان آزمایش کرد که آیا نقاط گلوله همانطور که انتظار می رود ظاهر می شوند یا خیر:
کاتلین
@Test fun textWithBulletPoints() { val result = builder.markdownToSpans("Points\n* one\n+ two") // Check whether the markup tags are removed. assertEquals("Points\none\ntwo", result.toString()) // Get all the spans attached to the SpannedString. val spans = result.getSpans<Any>(0, result.length, Any::class.java) // Check whether the correct number of spans are created. assertEquals(2, spans.size.toLong()) // Check whether the spans are instances of BulletPointSpan. val bulletSpan1 = spans[0] as BulletPointSpan val bulletSpan2 = spans[1] as BulletPointSpan // Check whether the start and end indices are the expected ones. assertEquals(7, result.getSpanStart(bulletSpan1).toLong()) assertEquals(11, result.getSpanEnd(bulletSpan1).toLong()) assertEquals(11, result.getSpanStart(bulletSpan2).toLong()) assertEquals(14, result.getSpanEnd(bulletSpan2).toLong()) }
جاوا
@Test public void textWithBulletPoints() { SpannedString result = builder.markdownToSpans("Points\n* one\n+ two"); // Check whether the markup tags are removed. assertEquals("Points\none\ntwo", result.toString()); // Get all the spans attached to the SpannedString. Object[] spans = result.getSpans(0, result.length(), Object.class); // Check whether the correct number of spans are created. assertEquals(2, spans.length); // Check whether the spans are instances of BulletPointSpan. BulletPointSpan bulletSpan1 = (BulletPointSpan) spans[0]; BulletPointSpan bulletSpan2 = (BulletPointSpan) spans[1]; // Check whether the start and end indices are the expected ones. assertEquals(7, result.getSpanStart(bulletSpan1)); assertEquals(11, result.getSpanEnd(bulletSpan1)); assertEquals(11, result.getSpanStart(bulletSpan2)); assertEquals(14, result.getSpanEnd(bulletSpan2)); }
برای نمونههای تست بیشتر، MarkdownBuilderTest را در GitHub ببینید.
بازه های سفارشی را آزمایش کنید
هنگام آزمایش، بررسی کنید که TextPaint
شامل تغییرات مورد انتظار باشد و عناصر صحیح روی Canvas
شما ظاهر شوند. برای مثال، یک پیادهسازی span سفارشی را در نظر بگیرید که یک نقطه گلوله را به متنی اضافه میکند. نقطه گلوله اندازه و رنگ مشخصی دارد و بین حاشیه سمت چپ ناحیه قابل ترسیم و نقطه گلوله فاصله وجود دارد.
می توانید رفتار این کلاس را با اجرای یک تست AndroidJUnit آزمایش کنید و موارد زیر را بررسی کنید:
- اگر دهانه را به درستی اعمال کنید، یک نقطه گلوله با اندازه و رنگ مشخص شده روی بوم ظاهر می شود و فضای مناسب بین حاشیه سمت چپ و نقطه گلوله وجود دارد.
- اگر دامنه را اعمال نکنید، هیچ یک از رفتارهای سفارشی ظاهر نمی شود.
اجرای این تست ها را می توانید در نمونه TextStyling در گیت هاب مشاهده کنید.
میتوانید تعاملات Canvas را با تمسخر بوم، ارسال شیء مسخرهشده به متد drawLeadingMargin()
و تأیید اینکه متدهای صحیح با پارامترهای صحیح فراخوانی شدهاند، آزمایش کنید.
میتوانید نمونههای آزمایش دهانه بیشتری را در BulletPointSpanTest بیابید.
بهترین روش ها برای استفاده از دهانه ها
بسته به نیاز شما، چندین راه کارآمد حافظه برای تنظیم متن در TextView
وجود دارد.
بدون تغییر متن زیر، یک بازه را ضمیمه یا جدا کنید
TextView.setText()
حاوی بارهای اضافی متعددی است که span ها را متفاوت مدیریت می کند. به عنوان مثال، می توانید یک شی متنی Spannable
را با کد زیر تنظیم کنید:
کاتلین
textView.setText(spannableObject)
جاوا
textView.setText(spannableObject);
هنگام فراخوانی این اضافه بار از setText()
، TextView
یک کپی از Spannable
شما به عنوان SpannedString
ایجاد می کند و آن را به عنوان CharSequence
در حافظه نگه می دارد. این به این معنی است که متن و دهانههای شما تغییر ناپذیر هستند، بنابراین وقتی میخواهید متن یا دهانهها را بهروزرسانی کنید، یک شی Spannable
جدید ایجاد کنید و دوباره setText()
را فراخوانی کنید، که همچنین باعث اندازهگیری مجدد و ترسیم مجدد طرحبندی میشود.
برای نشان دادن اینکه دهانه ها باید قابل تغییر باشند، می توانید به جای آن از setText(CharSequence text, TextView.BufferType type)
استفاده کنید، همانطور که در مثال زیر نشان داده شده است:
کاتلین
textView.setText(spannable, BufferType.SPANNABLE) val spannableText = textView.text as Spannable spannableText.setSpan( ForegroundColorSpan(color), 8, spannableText.length, SPAN_INCLUSIVE_INCLUSIVE )
جاوا
textView.setText(spannable, BufferType.SPANNABLE); Spannable spannableText = (Spannable) textView.getText(); spannableText.setSpan( new ForegroundColorSpan(color), 8, spannableText.getLength(), SPAN_INCLUSIVE_INCLUSIVE);
در این مثال، پارامتر BufferType.SPANNABLE
باعث می شود TextView
یک SpannableString
ایجاد کند و شی CharSequence
که توسط TextView
نگهداری می شود اکنون دارای نشانه گذاری قابل تغییر و متن غیرقابل تغییر است. برای بهروزرسانی دامنه، متن را بهعنوان Spannable
بازیابی کنید و سپس در صورت نیاز، دهانهها را بهروزرسانی کنید.
هنگامی که گستره ها را ضمیمه، جدا می کنید یا تغییر موقعیت می دهید، TextView
به طور خودکار به روز می شود تا تغییر را در متن منعکس کند. اگر یک ویژگی داخلی یک span موجود را تغییر میدهید، برای ایجاد تغییرات مربوط به ظاهر، invalidate()
یا برای ایجاد تغییرات مربوط به متریک requestLayout()
را فراخوانی کنید.
متن را در یک TextView چندین بار تنظیم کنید
در برخی موارد، مانند هنگام استفاده از RecyclerView.ViewHolder
، ممکن است بخواهید دوباره از TextView
استفاده کنید و متن را چندین بار تنظیم کنید. به طور پیشفرض، صرف نظر از اینکه BufferType
را تنظیم میکنید، TextView
یک کپی از شی CharSequence
ایجاد میکند و آن را در حافظه نگه میدارد. این همه بهروزرسانیهای TextView
را عمدی میکند—شما نمیتوانید شی CharSequence
اصلی را برای بهروزرسانی متن بهروزرسانی کنید. این بدان معناست که هر بار که متن جدیدی را تنظیم می کنید، TextView
یک شی جدید ایجاد می کند.
اگر میخواهید کنترل بیشتری بر این فرآیند داشته باشید و از ایجاد شی اضافی اجتناب کنید، میتوانید Spannable.Factory
خود را پیادهسازی کنید و newSpannable()
را لغو کنید. به جای ایجاد یک شیء متنی جدید، می توانید CharSequence
موجود را به عنوان Spannable
فرستاده و برگردانید، همانطور که در مثال زیر نشان داده شده است:
کاتلین
val spannableFactory = object : Spannable.Factory() { override fun newSpannable(source: CharSequence?): Spannable { return source as Spannable } }
Java
Spannable.Factory spannableFactory = new Spannable.Factory(){ @Override public Spannable newSpannable(CharSequence source) { return (Spannable) source; } };
هنگام تنظیم متن باید از textView.setText(spannableObject, BufferType.SPANNABLE)
استفاده کنید. در غیر این صورت، منبع CharSequence
به عنوان یک نمونه Spanned
ایجاد میشود و نمیتواند به Spannable
فرستاده شود، که باعث میشود newSpannable()
یک ClassCastException
را پرتاب کند.
پس از لغو newSpannable()
، به TextView
بگویید از Factory
جدید استفاده کند:
کاتلین
textView.setSpannableFactory(spannableFactory)
جاوا
textView.setSpannableFactory(spannableFactory);
شی Spannable.Factory
را یک بار، درست پس از اینکه به TextView
خود ارجاع دادید، تنظیم کنید. اگر از RecyclerView
استفاده میکنید، وقتی برای اولین بار نماهای خود را افزایش میدهید، شی Factory
را تنظیم کنید. هنگامی که RecyclerView
شما یک آیتم جدید را به ViewHolder
شما متصل می کند، از ایجاد شی اضافی جلوگیری می کند.
ویژگیهای span داخلی را تغییر دهید
اگر نیاز دارید که فقط یک ویژگی داخلی یک span قابل تغییر، مانند رنگ گلوله در یک گستره گلوله سفارشی را تغییر دهید، میتوانید با نگه داشتن ارجاع به span که ایجاد میشود، از فراخوانی چندباره setText()
جلوگیری کنید. هنگامی که نیاز به تغییر دامنه دارید، می توانید مرجع را تغییر دهید و سپس بر اساس نوع ویژگی که تغییر داده اید، invalidate()
یا requestLayout()
را در TextView
فراخوانی کنید.
در مثال کد زیر، یک پیادهسازی نقطه گلوله سفارشی دارای رنگ پیشفرض قرمز است که با ضربه زدن روی دکمه به خاکستری تغییر میکند:
کاتلین
class MainActivity : AppCompatActivity() { // Keeping the span as a field. val bulletSpan = BulletPointSpan(color = Color.RED) override fun onCreate(savedInstanceState: Bundle?) { ... val spannable = SpannableString("Text is spantastic") // Setting the span to the bulletSpan field. spannable.setSpan( bulletSpan, 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE ) styledText.setText(spannable) button.setOnClickListener { // Change the color of the mutable span. bulletSpan.color = Color.GRAY // Color doesn't change until invalidate is called. styledText.invalidate() } } }
جاوا
public class MainActivity extends AppCompatActivity { private BulletPointSpan bulletSpan = new BulletPointSpan(Color.RED); @Override protected void onCreate(Bundle savedInstanceState) { ... SpannableString spannable = new SpannableString("Text is spantastic"); // Setting the span to the bulletSpan field. spannable.setSpan(bulletSpan, 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE); styledText.setText(spannable); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Change the color of the mutable span. bulletSpan.setColor(Color.GRAY); // Color doesn't change until invalidate is called. styledText.invalidate(); } }); } }
از توابع افزونه Android KTX استفاده کنید
Android KTX همچنین دارای توابع افزودنی است که کار با دهانه ها را آسان تر می کند. برای کسب اطلاعات بیشتر، به مستندات بسته androidx.core.text مراجعه کنید.