स्पैन, मार्कअप ऑब्जेक्ट होते हैं. इनका इस्तेमाल करके, वर्ण या पैराग्राफ़ लेवल पर टेक्स्ट को स्टाइल किया जा सकता है. स्पैन को टेक्स्ट ऑब्जेक्ट से अटैच करके, टेक्स्ट में कई तरह के बदलाव किए जा सकते हैं. जैसे, रंग जोड़ना, टेक्स्ट को क्लिक करने लायक बनाना, टेक्स्ट के साइज़ को स्केल करना, और टेक्स्ट को अपनी पसंद के मुताबिक बनाना. स्पैन, 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 पैरामीटर, टेक्स्ट के उस हिस्से को दिखाते हैं जिस पर आपको स्पैन लागू करना है.
अगर स्पैन की सीमाओं के अंदर कोई टेक्स्ट डाला जाता है, तो स्पैन अपने-आप बड़ा हो जाता है, ताकि डाले गए टेक्स्ट को शामिल किया जा सके. स्पैन की सीमाओं पर टेक्स्ट डालने पर—यानी कि शुरू या आखिर के इंडेक्स पर—flags पैरामीटर यह तय करता है कि डाला गया टेक्स्ट शामिल करने के लिए स्पैन को बढ़ाया जाए या नहीं. जोड़ा गया टेक्स्ट शामिल करने के लिए, 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
सबक्लास यह तय करते हैं कि 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
को बढ़ाता है और updateDrawState
कॉलबैक को बदलकर TextPaint
का रंग सेट करता है:
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 sample में, इन टेस्ट को लागू करने का तरीका देखा जा सकता है.
कैनवस को मॉक करके, कैनवस इंटरैक्शन की जांच की जा सकती है. इसके लिए, मॉक किए गए ऑब्जेक्ट को 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
का फिर से इस्तेमाल करना पड़ सकता है. साथ ही, टेक्स्ट को कई बार सेट करना पड़ सकता है. डिफ़ॉल्ट रूप से, BufferType
को सेट किया गया है या नहीं, इससे कोई फ़र्क़ नहीं पड़ता. TextView
, CharSequence
ऑब्जेक्ट की एक कॉपी बनाता है और उसे मेमोरी में सेव करता है. इससे सभी 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);
Spannable.Factory
ऑब्जेक्ट को एक बार सेट करें. ऐसा तब करें, जब आपको अपने TextView
का रेफ़रंस मिल जाए. अगर 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 पैकेज का दस्तावेज़ देखें.