स्पैन, मार्कअप के ऐसे बेहतरीन ऑब्जेक्ट होते हैं जिनका इस्तेमाल, वर्ण या पैराग्राफ़ के लेवल पर टेक्स्ट को स्टाइल करने के लिए किया जा सकता है. टेक्स्ट ऑब्जेक्ट में स्पैन जोड़कर, टेक्स्ट को कई तरह से बदला जा सकता है. जैसे, रंग जोड़ना, टेक्स्ट पर क्लिक करने की सुविधा जोड़ना, टेक्स्ट का साइज़ बदलना, और अपनी पसंद के मुताबिक टेक्स्ट बनाना. स्पैन की मदद से, TextPaint
प्रॉपर्टी बदली जा सकती हैं, Canvas
पर ड्रॉ किया जा सकता है, और टेक्स्ट लेआउट बदला जा सकता है.
Android में कई तरह के स्पैन उपलब्ध होते हैं, जो टेक्स्ट के स्टाइल के कई सामान्य पैटर्न को कवर करते हैं. पसंद के मुताबिक स्टाइल लागू करने के लिए, अपने हिसाब से स्पैन भी बनाए जा सकते हैं.
स्पैन बनाना और लागू करना
स्पैन बनाने के लिए, नीचे दी गई टेबल में दी गई किसी क्लास का इस्तेमाल किया जा सकता है. क्लास अलग-अलग होती हैं. यह इस बात पर निर्भर करता है कि टेक्स्ट में बदलाव किया जा सकता है या नहीं, टेक्स्ट मार्कअप में बदलाव किया जा सकता है या नहीं, और स्पैन डेटा किस डेटा स्ट्रक्चर में मौजूद है.
कक्षा | बदलाव किया जा सकने वाला टेक्स्ट | बदले जा सकने वाला मार्कअप | डेटा स्ट्रक्चर |
---|---|---|---|
SpannedString |
नहीं | नहीं | लीनियर ऐरे |
SpannableString |
नहीं | हां | लीनियर ऐरे |
SpannableStringBuilder |
हां | हां | इंटरवल ट्री |
ये तीनों क्लास, Spanned
इंटरफ़ेस को एक्सटेंड करती हैं. SpannableString
और SpannableStringBuilder
भी Spannable
इंटरफ़ेस को बढ़ाते हैं.
इनमें से किसका इस्तेमाल करना है, यह तय करने का तरीका यहां बताया गया है:
- अगर बनाने के बाद टेक्स्ट या मार्कअप में बदलाव नहीं किया जा रहा है, तो
SpannedString
का इस्तेमाल करें. - अगर आपको किसी एक टेक्स्ट ऑब्जेक्ट में कुछ स्पैन अटैच करने हैं और टेक्स्ट खुद ही रीड-ओनली है, तो
SpannableString
का इस्तेमाल करें. - अगर आपको टेक्स्ट बनाने के बाद उसमें बदलाव करना है और आपको टेक्स्ट में स्पैन अटैच करने हैं, तो
SpannableStringBuilder
का इस्तेमाल करें. - अगर आपको किसी टेक्स्ट ऑब्जेक्ट में बड़ी संख्या में स्पैन अटैच करने हैं, तो
SpannableStringBuilder
का इस्तेमाल करें. इससे कोई फ़र्क़ नहीं पड़ता कि टेक्स्ट रीड-ओनली है या नहीं.
स्पैन लागू करने के लिए, Spannable
ऑब्जेक्ट पर setSpan(Object _what_, int _start_, int _end_, int
_flags_)
कॉल करें. what पैरामीटर से उस स्पैन के बारे में पता चलता है जिसे टेक्स्ट पर लागू किया जा रहा है. साथ ही, start और end पैरामीटर से उस टेक्स्ट के हिस्से के बारे में पता चलता है जिस पर स्पैन लागू किया जा रहा है.
अगर किसी स्पैन की सीमाओं के अंदर टेक्स्ट डाला जाता है, तो डाले गए टेक्स्ट को शामिल करने के लिए, स्पैन अपने-आप बड़ा हो जाता है. स्पैन की सीमाओं पर टेक्स्ट डालते समय, यानी शुरू या खत्म इंडेक्स पर, फ़्लैग पैरामीटर यह तय करता है कि डाले गए टेक्स्ट को शामिल करने के लिए स्पैन को बड़ा किया जाए या नहीं. डाले गए टेक्स्ट को शामिल करने के लिए, Spannable.SPAN_EXCLUSIVE_INCLUSIVE
फ़्लैग का इस्तेमाल करें. साथ ही, डाले गए टेक्स्ट को बाहर रखने के लिए, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
का इस्तेमाल करें.
यहां दिए गए उदाहरण में, किसी स्ट्रिंग में ForegroundColorSpan
अटैच करने का तरीका बताया गया है:
Kotlin
val spannable = SpannableStringBuilder("Text is spantastic!") spannable.setSpan( ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE )
Java
SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE );

ForegroundColorSpan
के साथ स्टाइल किया गया है.
स्पैन को Spannable.SPAN_EXCLUSIVE_INCLUSIVE
का इस्तेमाल करके सेट किया जाता है. इसलिए, स्पैन की सीमाओं पर डाले गए टेक्स्ट को शामिल करने के लिए, स्पैन का दायरा बढ़ जाता है. इस बारे में यहां दिए गए उदाहरण में बताया गया है:
Kotlin
val spannable = SpannableStringBuilder("Text is spantastic!") spannable.setSpan( ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE ) spannable.insert(12, "(& fon)")
Java
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)");

Spannable.SPAN_EXCLUSIVE_INCLUSIVE
का इस्तेमाल करने पर, स्पान बड़ा हो जाता है, ताकि उसमें
अतिरिक्त टेक्स्ट शामिल किया जा सके.
एक ही टेक्स्ट में कई स्पैन अटैच किए जा सकते हैं. यहां दिए गए उदाहरण में, बोल्ड और लाल रंग का टेक्स्ट बनाने का तरीका बताया गया है:
Kotlin
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 )
Java
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 );

ForegroundColorSpan(Color.RED)
और
StyleSpan(BOLD)
.
Android स्पैन टाइप
Android, android.text.style पैकेज में 20 से ज़्यादा तरह के स्पैन उपलब्ध कराता है. Android, स्पैन को दो मुख्य तरीकों से बांटता है:
- स्पैन का टेक्स्ट पर क्या असर पड़ता है: स्पैन का टेक्स्ट के दिखने या टेक्स्ट की मेट्रिक पर असर पड़ सकता है.
- स्पैन का दायरा: कुछ स्पैन, अलग-अलग वर्णों पर लागू किए जा सकते हैं, जबकि अन्य को पूरे पैराग्राफ़ पर लागू करना ज़रूरी है.

इन सेक्शन में, इन कैटगरी के बारे में ज़्यादा जानकारी दी गई है.
ऐसे स्पैन जिनसे टेक्स्ट के दिखने पर असर पड़ता है
वर्ण के लेवल पर लागू होने वाले कुछ स्पैन, टेक्स्ट के दिखने पर असर डालते हैं. जैसे, टेक्स्ट या बैकग्राउंड का रंग बदलना और अंडरलाइन या स्ट्राइकथ्रू जोड़ना. ये स्पान, CharacterStyle
क्लास को बड़ा करते हैं.
नीचे दिए गए कोड के उदाहरण में, टेक्स्ट के नीचे रेखा लगाने के लिए UnderlineSpan
को लागू करने का तरीका बताया गया है:
Kotlin
val string = SpannableString("Text with underline span") string.setSpan(UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
Java
SpannableString string = new SpannableString("Text with underline span"); string.setSpan(new UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

UnderlineSpan
का इस्तेमाल किया गया है.
सिर्फ़ टेक्स्ट के दिखने पर असर डालने वाले स्पैन, लेआउट का फिर से हिसाब लगाए बिना टेक्स्ट को फिर से दिखाते हैं. ये स्पैन,
UpdateAppearance
को लागू करते हैं और
CharacterStyle
को बढ़ाते हैं.
CharacterStyle
सबक्लास, TextPaint
को अपडेट करने का ऐक्सेस देकर, टेक्स्ट को ड्रॉ करने का तरीका तय करते हैं.
ऐसे स्पैन जिनका असर टेक्स्ट मेट्रिक पर पड़ता है
वर्ण लेवल पर लागू होने वाले अन्य स्पैन, टेक्स्ट मेट्रिक पर असर डालते हैं. जैसे, लाइन की ऊंचाई और टेक्स्ट का साइज़. ये स्पैन, MetricAffectingSpan
क्लास को बड़ा करते हैं.
नीचे दिए गए कोड के उदाहरण में, ऐसा RelativeSizeSpan
बनाया गया है जो टेक्स्ट के साइज़ को 50% बढ़ाता है:
Kotlin
val string = SpannableString("Text with relative size span") string.setSpan(RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
Java
SpannableString string = new SpannableString("Text with relative size span"); string.setSpan(new RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

RelativeSizeSpan
का इस्तेमाल किया गया.
टेक्स्ट मेट्रिक पर असर डालने वाला स्पैन लागू करने पर, निगरानी करने वाला ऑब्जेक्ट, सही लेआउट और रेंडरिंग के लिए टेक्स्ट को फिर से मेज़र करता है. उदाहरण के लिए, टेक्स्ट के साइज़ में बदलाव करने से, शब्द अलग-अलग लाइनों पर दिख सकते हैं. टेक्स्ट के पहले वाले हिस्से पर स्पैन लागू करने से, टेक्स्ट लेआउट को फिर से मेज़र किया जाता है और उसका हिसाब फिर से लगाया जाता है. साथ ही, टेक्स्ट को फिर से ड्रॉ किया जाता है.
टेक्स्ट मेट्रिक पर असर डालने वाले स्पैन, MetricAffectingSpan
क्लास को बढ़ाते हैं. यह एक ऐसी ऐब्स्ट्रैक्ट क्लास है जो सबक्लास को यह तय करने की सुविधा देती है कि स्पैन, TextPaint
का ऐक्सेस देकर टेक्स्ट मेज़रमेंट पर कैसे असर डालता है. MetricAffectingSpan
, CharacterStyle
को बढ़ाता है. इसलिए, सबक्लास, वर्ण के लेवल पर टेक्स्ट के दिखने पर असर डालते हैं.
पैराग्राफ़ पर असर डालने वाले स्पैन
स्पैन का असर पैराग्राफ़ लेवल पर भी पड़ सकता है. जैसे, टेक्स्ट के ब्लॉक के अलाइनमेंट या मार्जिन में बदलाव करना. पूरे पैराग्राफ़ पर असर डालने वाले स्पैन, ParagraphStyle
लागू करते हैं. इन स्पैन का इस्तेमाल करने के लिए, उन्हें पूरे पैराग्राफ़ से अटैच करें. हालांकि, पैराग्राफ़ के आखिर में मौजूद नई लाइन के वर्ण को अटैच न करें. अगर पूरे पैराग्राफ के बजाय, किसी और चीज़ पर पैराग्राफ स्पैन लागू करने की कोशिश की जाती है, तो Android स्पैन को लागू नहीं करता.
आठवें चित्र में दिखाया गया है कि Android, टेक्स्ट में पैराग्राफ़ को कैसे अलग करता है.

\n
) का वर्ण होता है.
यहां दिए गए कोड के उदाहरण में, पैराग्राफ पर QuoteSpan
लागू किया गया है. ध्यान दें कि अगर आपने पैराग्राफ़ की शुरुआत या आखिर के अलावा किसी और जगह पर स्पैन अटैच किया है, तो Android उस पर स्टाइल लागू नहीं करता.
Kotlin
spannable.setSpan(QuoteSpan(color), 8, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
Java
spannable.setSpan(new QuoteSpan(color), 8, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

QuoteSpan
.
कस्टम स्पैन बनाना
अगर आपको मौजूदा Android स्पान में दिए गए फ़ंक्शन के अलावा ज़्यादा फ़ंक्शन चाहिए, तो कस्टम स्पान लागू किया जा सकता है. अपना स्पैन लागू करते समय, तय करें कि आपके स्पैन का असर टेक्स्ट के वर्ण लेवल पर होगा या पैराग्राफ़ लेवल पर. साथ ही, यह भी तय करें कि इसका असर टेक्स्ट के लेआउट या उसके दिखने के तरीके पर होगा या नहीं. इससे आपको यह तय करने में मदद मिलती है कि किन बेस क्लास को एक्सटेंड किया जा सकता है और किन इंटरफ़ेस को लागू करने की ज़रूरत पड़ सकती है. रेफ़रंस के लिए, यहां दी गई टेबल का इस्तेमाल करें:
स्थिति | क्लास या इंटरफ़ेस |
---|---|
आपके स्पैन का असर, वर्ण के लेवल पर टेक्स्ट पर पड़ता है. | CharacterStyle |
स्पैन से टेक्स्ट के दिखने के तरीके पर असर पड़ता है. | UpdateAppearance |
आपके स्पैन से टेक्स्ट मेट्रिक पर असर पड़ता है. | UpdateLayout |
आपके स्पैन का असर पैराग्राफ़ लेवल पर टेक्स्ट पर पड़ता है. | ParagraphStyle |
उदाहरण के लिए, अगर आपको टेक्स्ट के साइज़ और रंग में बदलाव करने वाला कस्टम स्पैन लागू करना है, तो RelativeSizeSpan
को बड़ा करें. इनहेरिटेंस की मदद से, RelativeSizeSpan
CharacterStyle
को एक्सटेंड करता है और दो Update
इंटरफ़ेस लागू करता है. इस क्लास में, updateDrawState
और updateMeasureState
के लिए पहले से ही कॉलबैक उपलब्ध होते हैं. इसलिए, अपने कस्टम व्यवहार को लागू करने के लिए, इन कॉलबैक को बदला जा सकता है. यहां दिया गया कोड, एक कस्टम स्पैन बनाता है जो RelativeSizeSpan
को बड़ा करता है और TextPaint
का रंग सेट करने के लिए updateDrawState
कॉलबैक को बदल देता है:
Kotlin
class RelativeSizeColorSpan( size: Float, @ColorInt private val color: Int ) : RelativeSizeSpan(size) { override fun updateDrawState(textPaint: TextPaint) { super.updateDrawState(textPaint) textPaint.color = color } }
Java
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 जांच लागू करें. इससे यह पुष्टि की जा सकती है कि सही स्पैन सही जगहों पर जोड़े गए हैं. टेक्स्ट स्टाइल के सैंपल ऐप्लिकेशन में एक स्पैन होता है, जो टेक्स्ट में BulletPointSpan
अटैच करके, बुलेट पॉइंट पर मार्कअप लागू करता है. यहां दिए गए कोड के उदाहरण में, यह जांचने का तरीका बताया गया है कि बुलेट पॉइंट उम्मीद के मुताबिक दिख रहे हैं या नहीं:
Kotlin
@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()) }
Java
@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)); }
जांच के ज़्यादा उदाहरणों के लिए, GitHub पर MarkdownBuilderTest देखें.
कस्टम स्पैन की जांच करना
स्पैन की जांच करते समय, पुष्टि करें कि TextPaint
में उम्मीद के मुताबिक बदलाव किए गए हैं और आपके Canvas
पर सही एलिमेंट दिख रहे हैं. उदाहरण के लिए, किसी टेक्स्ट के आगे बुलेट पॉइंट जोड़ने के लिए, कस्टम स्पैन लागू करें. बुलेट पॉइंट का साइज़ और रंग तय होता है. साथ ही, ड्रॉ किए जा सकने वाले हिस्से के बाएं मार्जिन और बुलेट पॉइंट के बीच एक गैप होता है.
AndroidJUnit टेस्ट लागू करके, इस क्लास के व्यवहार की जांच की जा सकती है. इसके लिए, इन बातों की जांच करें:
- स्पैन को सही तरीके से लागू करने पर, कैनवस पर तय किए गए साइज़ और रंग का बुलेट पॉइंट दिखता है. साथ ही, बाईं ओर मौजूद मार्जिन और बुलेट पॉइंट के बीच सही स्पेस होता है.
- स्पैन लागू न करने पर, कोई भी कस्टम व्यवहार नहीं दिखता.
GitHub पर TextStyling के सैंपल में, इन टेस्ट को लागू करने का तरीका देखा जा सकता है.
कैनवस के इंटरैक्शन की जांच करने के लिए, कैनवस को मॉक करें. इसके बाद, मॉक किए गए ऑब्जेक्ट को drawLeadingMargin()
विधि में पास करें और पुष्टि करें कि सही तरीकों को सही पैरामीटर के साथ कॉल किया गया है.
आपको BulletPointSpanTest में, स्पैन टेस्ट के ज़्यादा सैंपल मिल सकते हैं.
स्पैन इस्तेमाल करने के सबसे सही तरीके
TextView
में टेक्स्ट सेट करने के कई तरीके हैं. ये तरीके, आपकी ज़रूरतों के हिसाब से तय किए जाते हैं.
टेक्स्ट में बदलाव किए बिना, स्पैन को अटैच या डिटैच करना
TextView.setText()
में कई ओवरलोड होते हैं, जो अलग-अलग तरह से स्पैन को हैंडल करते हैं. उदाहरण के लिए, नीचे दिए गए कोड की मदद से Spannable
टेक्स्ट ऑब्जेक्ट सेट किया जा सकता है:
Kotlin
textView.setText(spannableObject)
Java
textView.setText(spannableObject);
setText()
के इस ओवरलोड को कॉल करते समय, TextView
आपके Spannable
की कॉपी को SpannedString
के तौर पर बनाता है और उसे CharSequence
के तौर पर मेमोरी में सेव रखता है.
इसका मतलब है कि आपका टेक्स्ट और स्पैन में बदलाव नहीं किया जा सकता. इसलिए, जब आपको टेक्स्ट या स्पैन अपडेट करने हों, तो नया Spannable
ऑब्जेक्ट बनाएं और setText()
को फिर से कॉल करें. इससे लेआउट को फिर से मेज़र करने और फिर से ड्रॉ करने की प्रोसेस भी ट्रिगर होती है.
यह दिखाने के लिए कि स्पैन में बदलाव किया जा सकता है, इसके बजाय setText(CharSequence text, TextView.BufferType
type)
का इस्तेमाल किया जा सकता है, जैसा कि इस उदाहरण में दिखाया गया है:
Kotlin
textView.setText(spannable, BufferType.SPANNABLE) val spannableText = textView.text as Spannable spannableText.setSpan( ForegroundColorSpan(color), 8, spannableText.length, SPAN_INCLUSIVE_INCLUSIVE )
Java
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
बनाता है. साथ ही, TextView
के पास मौजूद CharSequence
ऑब्जेक्ट में अब बदलाव किया जा सकने वाला मार्कअप और बदलाव न किया जा सकने वाला टेक्स्ट है. स्पैन को अपडेट करने के लिए, टेक्स्ट को Spannable
के तौर पर वापस पाएं. इसके बाद, ज़रूरत के हिसाब से स्पैन अपडेट करें.
स्पैन को अटैच, डिटैच या किसी दूसरी जगह पर ले जाने पर, TextView
अपने-आप अपडेट हो जाता है, ताकि टेक्स्ट में हुए बदलाव दिख सकें. अगर किसी मौजूदा स्पैन के किसी इंटरनल एट्रिब्यूट में बदलाव किया जाता है, तो दिखने से जुड़े बदलाव करने के लिए invalidate()
या मेट्रिक से जुड़े बदलाव करने के लिए requestLayout()
को कॉल करें.
TextView में टेक्स्ट को कई बार सेट करना
कुछ मामलों में, जैसे कि RecyclerView.ViewHolder
का इस्तेमाल करते समय, हो सकता है कि आपको TextView
का फिर से इस्तेमाल करना हो और टेक्स्ट को कई बार सेट करना हो. डिफ़ॉल्ट रूप से, TextView
, CharSequence
ऑब्जेक्ट की कॉपी बनाता है और उसे मेमोरी में सेव रखता है. भले ही, आपने BufferType
को सेट किया हो या नहीं. इससे सभी
TextView
अपडेट जान-बूझकर किए जाते हैं—टेक्स्ट अपडेट करने के लिए, ओरिजनल
CharSequence
ऑब्जेक्ट को अपडेट नहीं किया जा सकता. इसका मतलब है कि जब भी नया टेक्स्ट सेट किया जाता है, तो TextView
एक नया ऑब्जेक्ट बनाता है.
अगर आपको इस प्रोसेस पर ज़्यादा कंट्रोल चाहिए और अतिरिक्त ऑब्जेक्ट बनाने से बचना है, तो अपने Spannable.Factory
को लागू करें और newSpannable()
को बदलें.
नया टेक्स्ट ऑब्जेक्ट बनाने के बजाय, मौजूदा CharSequence
को Spannable
के तौर पर कास्ट और दिखाया जा सकता है. इसका उदाहरण यहां दिया गया है:
Kotlin
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
का इस्तेमाल करने के लिए कहें:
Kotlin
textView.setSpannableFactory(spannableFactory)
Java
textView.setSpannableFactory(spannableFactory);
TextView
का रेफ़रंस मिलने के तुरंत बाद, Spannable.Factory
ऑब्जेक्ट को एक बार सेट करें. अगर RecyclerView
का इस्तेमाल किया जा रहा है, तो पहली बार व्यू बढ़ाते समय Factory
ऑब्जेक्ट सेट करें. इससे, जब आपका RecyclerView
किसी नए आइटम को ViewHolder
से बांधता है, तो अतिरिक्त ऑब्जेक्ट बनाने से बचा जा सकता है.
इंटरनल स्पैन एट्रिब्यूट बदलना
अगर आपको बदलाव किए जा सकने वाले स्पैन का सिर्फ़ कोई एक इंटरनल एट्रिब्यूट बदलना है, जैसे कि कस्टम बुलेट स्पैन में बुलेट का रंग, तो स्पैन के बनाए जाने के बाद उसका रेफ़रंस रखकर, setText()
को कई बार कॉल करने से बचा जा सकता है.
जब आपको स्पैन में बदलाव करना हो, तो रेफ़रंस में बदलाव करें. इसके बाद, बदले गए एट्रिब्यूट के टाइप के आधार पर, TextView
पर invalidate()
या requestLayout()
को कॉल करें.
नीचे दिए गए कोड के उदाहरण में, कस्टम बुलेट पॉइंट लागू करने का डिफ़ॉल्ट रंग लाल है. बटन पर टैप करने पर, यह रंग स्लेटी में बदल जाता है:
Kotlin
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() } } }
Java
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 पैकेज का दस्तावेज़ देखें.