SpannableString Android SDK का एक क्लास है जो android.text पैकेज से आता है और आपको TextView में एक ही टेक्स्ट स्ट्रिंग के अलग-अलग हिस्सों पर कई स्टाइल लागू करने की अनुमति देता है। HTML मार्कअप के विपरीत, SpannableString Span ऑब्जेक्ट के स्तर पर काम करता है, टेक्स्ट के विज़ुअल डिस्प्ले को नियंत्रित करता है: रंग, आकार, फ़ॉन्ट, अंडरलाइन और इंटरैक्टिव तत्व। Google Developers के अनुसार, SpannableString का उपयोग Android सिस्टम घटकों में लिंक फ़ॉर्मेटिंग के लिए किया जाता है। यह तीसरे पक्ष की लाइब्रेरी के बिना टेक्स्ट स्टाइल करने का प्राथमिक तरीका है।
मुख्य बातें
SpannableString एक Android क्लास है जो Spannable इंटरफ़ेस को लागू करता है, टेक्स्ट को Span ऑब्जेक्ट के सेट के साथ संग्रहीत करता है जो विज़ुअल डिस्प्ले को नियंत्रित करते हैं। सामान्य String के विपरीत, SpannableString विशिष्ट वर्ण रेंज में स्टाइल विशेषताएँ संलग्न करने की अनुमति देता है: टेक्स्ट के हिस्से को लाल बनाना, हेडिंग में फ़ॉन्ट आकार बढ़ाना, या पैराग्राफ के अंदर एक क्लिक करने योग्य लिंक जोड़ना।
यह क्लास android.text पैकेज में है और API Level 1 से उपलब्ध है। SpannableString अपरिवर्तनीय है — एक बार बनाने के बाद इसकी संरचना निश्चित हो जाती है, और टेक्स्ट बदलने के लिए एक नया ऑब्जेक्ट बनाना पड़ता है। डायनामिक संपादन के लिए SpannableStringBuilder का उपयोग किया जाता है, जो स्टाइल खोए बिना वर्ण सम्मिलित और हटाने का समर्थन करता है।
CharSequence टेक्स्ट डेटा के लिए आधार इंटरफ़ेस है, जिसे String, StringBuilder और SpannableString लागू करते हैं। SpannableString और String के बीच मुख्य अंतर उप-स्ट्रिंग में मनमाना ऑब्जेक्ट संलग्न करने का समर्थन है। TextView Spannable इंटरफ़ेस को पहचानता है और रेंडरिंग के दौरान संबंधित टेक्स्ट खंडों पर स्पैन ऑब्जेक्ट लागू करता है। यदि आप TextView में एक सामान्य String पास करते हैं, तो कोई स्टाइल लागू नहीं होगा।
SpannableString टेक्स्ट को char[] ऐरे और स्पैन ऑब्जेक्ट के एक अलग ऐरे में प्रारंभ और अंत स्थिति के मेटाडेटा के साथ संग्रहीत करता है। जब setSpan(what, start, end, flags) कॉल किया जाता है, तो what ऑब्जेक्ट रेंज जानकारी के साथ सूची में सहेजा जाता है। रेंडरिंग के दौरान, TextView प्रदर्शित रेंज में आने वाले सभी स्पैन को क्रमिक रूप से लागू करता है, updateDrawState और updateMeasureState विधियों को कॉल करता है।
CharacterStyle स्पैन के लिए आधार क्लास है जो लाइनों में उनकी स्थिति की परवाह किए बिना व्यक्तिगत वर्णों को प्रभावित करता है। इसमें ForegroundColorSpan (टेक्स्ट रंग), RelativeSizeSpan (सापेक्ष आकार), StyleSpan (बोल्ड और इटैलिक), UnderlineSpan (अंडरलाइन) और अन्य शामिल हैं। कैरेक्टर स्पैन निर्दिष्ट रेंज में प्रत्येक वर्ण पर व्यक्तिगत रूप से लागू होते हैं।
ParagraphStyle स्पैन के लिए एक इंटरफ़ेस है जो पूरे पैराग्राफ को प्रभावित करता है। सबसे प्रसिद्ध प्रतिनिधि AlignmentSpan है, जो पूरे पैराग्राफ को बाएँ, केंद्र या दाएँ संरेखित करता है। पैराग्राफ स्पैन को पूरे पैराग्राफ को कवर करना चाहिए; अन्यथा, Android उनके आवेदन को अनदेखा करता है। यह सीमा इसलिए है क्योंकि संरेखण या इंडेंटेशन केवल पूरे टेक्स्ट ब्लॉक के लिए समझ में आता है।
Span फ़्लैग चार स्थिरांक हैं जो स्पैन के व्यवहार को परिभाषित करते हैं जब इसकी रेंज की सीमाओं पर टेक्स्ट डाला या हटाया जाता है। SPAN_EXCLUSIVE_EXCLUSIVE स्पैन को केवल मूल सीमाओं के भीतर सक्रिय रखता है, SPAN_INCLUSIVE_INCLUSIVE सीमाओं पर टेक्स्ट जोड़ने पर इसका विस्तार करता है। SPAN_EXCLUSIVE_INCLUSIVE और SPAN_INCLUSIVE_EXCLUSIVE रेंज की शुरुआत और अंत के लिए मिश्रित व्यवहार प्रदान करते हैं।
| फ़्लैग | बाईं ओर सम्मिलन | दाईं ओर सम्मिलन |
|---|---|---|
| SPAN_EXCLUSIVE_EXCLUSIVE | शामिल नहीं करता | शामिल नहीं करता |
| SPAN_INCLUSIVE_INCLUSIVE | शामिल करता है | शामिल करता है |
| SPAN_EXCLUSIVE_INCLUSIVE | शामिल नहीं करता | शामिल करता है |
| SPAN_INCLUSIVE_EXCLUSIVE | शामिल करता है | शामिल नहीं करता |
EditText में Editable टेक्स्ट के लिए सही फ़्लैग चुनना महत्वपूर्ण है, जहाँ उपयोगकर्ता वर्ण सम्मिलित और हटा सकता है। केवल-पढ़ने वाले TextView के लिए, आमतौर पर SPAN_EXCLUSIVE_EXCLUSIVE का उपयोग किया जाता है — स्टाइल केवल मूल रेंज पर लागू होता है और प्रोग्रामेटिक परिवर्तनों के साथ विस्तारित नहीं होता।
Android SDK 25 से अधिक अंतर्निहित स्पैन क्लासेस प्रदान करता है जो अधिकांश टेक्स्ट स्टाइलिंग कार्यों को कवर करते हैं। प्रत्येक क्लास CharacterStyle या ParagraphStyle इंटरफ़ेस को लागू करता है और अपने कंस्ट्रक्टर के माध्यम से पैरामीटर स्वीकार करता है। सभी क्लासेस android.text.style पैकेज में हैं और अतिरिक्त निर्भरताएँ जोड़े बिना उपलब्ध हैं।
ForegroundColorSpan निर्दिष्ट रेंज के लिए टेक्स्ट रंग सेट करता है, int प्रारूप में रंग स्वीकार करता है। BackgroundColorSpan टेक्स्ट के पीछे की पृष्ठभूमि को पेंट करता है, जो खोज परिणामों को हाइलाइट करने के लिए उपयोगी है। AbsoluteSizeSpan पिक्सेल में सटीक फ़ॉन्ट आकार सेट करता है, RelativeSizeSpan TextView में आधार टेक्स्ट आकार के सापेक्ष गुणक लागू करता है।
StyleSpan Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC या BOLD_ITALIC स्थिरांक स्वीकार करता है और वर्णों का टाइपफ़ेस बदलता है। UnderlineSpan अंडरलाइन जोड़ता है, StrikethroughSpan स्ट्राइकथ्रू जोड़ता है। SuperscriptSpan और SubscriptSpan सुपरस्क्रिप्ट और सबस्क्रिप्ट बनाते हैं। TypefaceSpan टेक्स्ट रेंज के लिए Typeface ऑब्जेक्ट के माध्यम से कस्टम फ़ॉन्ट सेट करने की अनुमति देता है।
ClickableSpan क्लिक करने योग्य टेक्स्ट सेगमेंट बनाने के लिए एक अमूर्त क्लास है। टैप करने पर, onClick() विधि कॉल की जाती है। क्लिक के काम करने के लिए, TextView में setMovementMethod(LinkMovementMethod.getInstance()) होना चाहिए। URLSpan हाइपरलिंक के लिए ClickableSpan की उपश्रेणी है जो स्वचालित रूप से ब्राउज़र खोलता है। ClickableSpan को अक्सर ForegroundColorSpan के साथ जोड़ा जाता है ताकि लिंक को नीले रंग में दृश्य रूप से हाइलाइट किया जा सके।
val spannable = SpannableString("Open developer.android.com")
spannable.setSpan(
URLSpan("https://developer.android.com"),
9, 31, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
ForegroundColorSpan(Color.BLUE),
9, 31, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
textView.movementMethod = LinkMovementMethod.getInstance()
LinkMovementMethod के बिना, URLSpan पर क्लिक संसाधित नहीं होंगे। MovementMethod स्पर्श घटनाओं को इंटरसेप्ट करने और स्पर्श स्थिति पर ClickableSpan खोजने के लिए जिम्मेदार है। रंग स्पैन लिंक को उपयोगकर्ता के लिए दृश्यमान बनाता है।
SpannableString के साथ काम करना एक टेक्स्ट स्ट्रिंग से इंस्टेंस बनाने और setSpan() विधि के माध्यम से क्रमिक रूप से स्पैन लागू करने से शुरू होता है। विधि चार पैरामीटर लेती है: स्पैन ऑब्जेक्ट, प्रारंभ स्थिति, अंत स्थिति और फ़्लैग। सभी स्पैन सेट करने के बाद, ऑब्जेक्ट setText() के माध्यम से TextView को पास किया जाता है।
आइए एक स्ट्रिंग बनाएँ जहाँ पहला शब्द लाल और बड़ा हो। इसके लिए, हम रंग के लिए ForegroundColorSpan और स्केल के लिए RelativeSizeSpan का उपयोग करते हैं। दोनों स्पैन स्वतंत्र रूप से एक ही रेंज पर लागू होते हैं — setSpan कॉल का क्रम मायने नहीं रखता।
val text = "Header: remaining text"
val spannable = SpannableString(text)
val colorSpan = ForegroundColorSpan(Color.RED)
val sizeSpan = RelativeSizeSpan(1.5f)
spannable.setSpan(colorSpan, 0, 9, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
spannable.setSpan(sizeSpan, 0, 9, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = spannable
स्थिति 0 से 9 तक के वर्ण एक साथ दोनों स्टाइल प्राप्त करते हैं। TextView रेंडरिंग के दौरान स्वचालित रूप से सभी स्पैन लागू करता है — किसी अतिरिक्त कॉल की आवश्यकता नहीं है। 1.5f के गुणक के साथ RelativeSizeSpan आधार के सापेक्ष फ़ॉन्ट आकार 50% बढ़ाता है।
Html.fromHtml() HTML स्ट्रिंग से Spanned ऑब्जेक्ट बनाता है, लेकिन समर्थित टैग का सेट सीमित है। SpannableString बिना HTML सीमाओं के प्रत्येक विशेषता पर पूर्ण नियंत्रण देता है। यदि आपको HTML को स्पैन में बदलने और फिर कस्टम स्टाइल जोड़ने की आवश्यकता है, तो आप Html.fromHtml() को आधार के रूप में उपयोग कर सकते हैं और फिर setSpan() के माध्यम से स्पैन के साथ पूरक कर सकते हैं।
val htmlText = Html.fromHtml(
"<b>Important:</b> check the data",
Html.FROM_HTML_MODE_LEGACY
)
val spannable = SpannableString(htmlText)
spannable.setSpan(
ForegroundColorSpan(Color.RED),
0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
परिणाम — टेक्स्ट “महत्वपूर्ण:” बोल्ड (HTML से) और लाल (स्पैन से) होगा। यह दृष्टिकोण सर्वर सामग्री के साथ काम करते समय सुविधाजनक है जहाँ फ़ॉर्मेटिंग का कुछ हिस्सा HTML में निर्दिष्ट होता है और कुछ हिस्सा क्लाइंट पक्ष पर प्रोग्रामेटिक रूप से जोड़ा जाता है।
SpannableString एक ही या ओवरलैपिंग रेंज पर असीमित संख्या में स्पैन लागू करने की अनुमति देता है। स्पैन को संयोजित करना HTML मार्कअप पर एक मुख्य लाभ है, जहाँ नेस्टेड टैग संघर्ष कर सकते हैं। स्पैन स्वतंत्र होते हैं और रेंडरिंग के दौरान क्रमिक रूप से लागू होते हैं।
उदाहरण के लिए, आप टेक्स्ट सेगमेंट को एक साथ बोल्ड, लाल और क्लिक करने योग्य बना सकते हैं। ऐसा करने के लिए, तीन स्पैन बनाएँ — StyleSpan, ForegroundColorSpan और ClickableSpan — और प्रत्येक को एक ही रेंज पर लागू करें। आवेदन का क्रम परिणाम को प्रभावित नहीं करता, क्योंकि प्रत्येक स्पैन अपनी स्वयं की टेक्स्ट विशेषता के लिए जिम्मेदार है।
यदि विभिन्न प्रकार के स्पैन आंशिक रूप से ओवरलैप होते हैं, तो प्रत्येक अपनी सीमाओं के भीतर स्वतंत्र रूप से काम करता है। रेंज 0–10 पर ForegroundColorSpan और रेंज 5–15 पर StyleSpan(BOLD) सेगमेंट 5–10 पर बोल्ड लाल टेक्स्ट और 10–15 पर केवल बोल्ड देगा। कोई संघर्ष उत्पन्न नहीं होता क्योंकि प्रत्येक स्पैन रेंडरिंग के दौरान अपनी स्वयं की विशेषता को संशोधित करता है।
getSpans(int start, int end, Class type) विधि निर्दिष्ट रेंज के भीतर स्पैन की एक ऐरे लौटाती है। यह जाँचने के लिए उपयोगी है कि कौन से स्टाइल पहले से लागू हैं, या विशिष्ट स्पैन को हटाने के लिए। nextSpanTransition() के साथ, आप स्पैन परिवर्तन सीमाओं पर पुनरावृति कर सकते हैं — यह कस्टम TextView कार्यान्वयन का आधार है जिन्हें यह जानने की आवश्यकता होती है कि स्टाइल कहाँ बदलता है।
SpannableStringBuilder खंडों को सम्मिलित करने, बदलने और हटाने की क्षमता के साथ स्टाइल किए गए टेक्स्ट के चरण-दर-चरण निर्माण के लिए एक क्लास है। SpannableString के विपरीत, जो एक तैयार स्ट्रिंग से बनाया जाता है और अपरिवर्तनीय है, Builder टेक्स्ट भागों को क्रमिक रूप से जोड़ने और चलते-फिरते स्टाइल निर्दिष्ट करने की अनुमति देता है। यह मिश्रित संदेशों के लिए आदर्श है: लॉग, चैट, डायनामिक लेबल वाले समाचार शीर्षक।
Builder Spannable और Editable इंटरफ़ेस लागू करता है, जो इसे EditText के साथ संगत बनाता है। उपयोगकर्ता टेक्स्ट संपादित कर सकता है, और स्टाइल संरक्षित रहते हैं और नए वर्ण सम्मिलित करने पर सही ढंग से स्थानांतरित होते हैं। SpannableString, अपरिवर्तनीय होने के कारण, संपादन योग्य फ़ील्ड के लिए उपयुक्त नहीं है।
append() विधि builder को ही लौटाती है, जिससे विधि श्रृंखलन संभव होता है। टेक्स्ट जोड़ने के बाद, setSpan() के माध्यम से स्पैन लागू किए जाते हैं। स्थितियाँ वर्तमान builder लंबाई के सापेक्ष निर्दिष्ट की जाती हैं। अधिक सटीक सामग्री नियंत्रण के लिए Insert() और replace() भी उपलब्ध हैं।
val builder = SpannableStringBuilder()
.append("New ")
.append("comment")
val blue = ForegroundColorSpan(Color.BLUE)
val gray = ForegroundColorSpan(Color.GRAY)
builder.setSpan(blue, 0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
builder.setSpan(gray, 6, 17, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = builder
टेक्स्ट “नया ” नीले रंग में और “टिप्पणी” ग्रे में रंगा हुआ है। उनके बीच अतिरिक्त वर्ण सम्मिलित करने पर, EXCLUSIVE फ़्लैग के कारण स्पैन नए टेक्स्ट को प्रभावित नहीं करेगा। Builder संशोधन पर स्वचालित रूप से आंतरिक सूचकांकों को समायोजित करता है।
बड़ी संख्या में स्पैन का उपयोग TextView के रेंडरिंग प्रदर्शन को प्रभावित करता है। प्रत्येक स्पैन प्रत्येक पुनः ड्रा पर updateDrawState() या updateMeasureState() विधि को कॉल करता है। मध्य-श्रेणी के उपकरणों पर आरामदायक प्रदर्शन के लिए प्रति TextView 50–100 स्पैन तक सीमित रखने की अनुशंसा की जाती है। टेक्स्ट आकार बदलने वाले स्पैन (RelativeSizeSpan, AbsoluteSizeSpan) को प्रत्येक परिवर्तन पर लेआउट पुनर्गणना की आवश्यकता होती है, जो केवल रंग या अंडरलाइन स्पैन की तुलना में काफी महंगा है।
TextAppearanceSpan एकल setSpan() कॉल के साथ android:textAppearance XML संसाधन से स्टाइल का पूरा सेट लागू करने की अनुमति देता है। तीन अलग-अलग स्पैन (रंग, आकार, फ़ॉन्ट) के बजाय, स्टाइल संदर्भ के साथ एक एकल TextAppearanceSpan का उपयोग किया जाता है। इससे ऑब्जेक्ट की संख्या कम होती है और रखरखाव सरल होता है — संसाधन में स्टाइल बदलना स्वचालित रूप से इस स्पैन का उपयोग करने वाले सभी टेक्स्ट पर लागू होता है।
प्रत्येक setSpan() के लिए एक नया स्पैन इंस्टेंस बनाने से कचरा संग्रहकर्ता पर अतिरिक्त भार पड़ता है। यदि उनका बार-बार उपयोग किया जाता है तो स्थिर स्पैन ऑब्जेक्ट बनाना इष्टतम है। उदाहरण के लिए, ForegroundColorSpan(Color.RED) को companion object में संग्रहीत किया जा सकता है और पुन: उपयोग किया जा सकता है। हालाँकि, स्थिति वाले स्पैन (विभिन्न हैंडलर वाले ClickableSpan) प्रत्येक मामले के लिए व्यक्तिगत रूप से बनाए जाने चाहिए।
स्पैन प्रदर्शन समस्याओं के निदान के लिए, Android Studio में Layout Inspector और GPU प्रोफ़ाइलर का उपयोग करें। यदि कई स्पैन वाला TextView स्क्रॉल करते समय काफ़ी धीमा हो जाता है, तो TextAppearanceSpan के माध्यम से कुछ स्पैन को स्थिर स्टाइल से बदलने या विशेषताओं को कस्टम UpdateAppearance कार्यान्वयन में संयोजित करके स्पैन की संख्या कम करने पर विचार करें।
अक्सर पूछे जाने वाले प्रश्न
String स्टाइल समर्थन के बिना वर्णों का एक अपरिवर्तनीय अनुक्रम है। SpannableString समान वर्णों को संग्रहीत करता है लेकिन अतिरिक्त रूप से फ़ॉर्मेटिंग जानकारी के साथ Span ऑब्जेक्ट की एक ऐरे रखता है। TextView पास किए गए CharSequence के प्रकार का निर्धारण करता है और रेंडरिंग के दौरान संबंधित रेंज पर स्पैन लागू करता है। String किसी भी स्टाइल विशेषता को अनदेखा करता है और सादे टेक्स्ट के रूप में प्रदर्शित होता है।
removeSpan(Object span) विधि एक विशिष्ट स्पैन को हटाती है। पूर्ण सफाई के लिए, getSpans(0, length, Object::class.java) कॉल करें, जो सभी स्पैन की एक ऐरे लौटाता है, फिर प्रत्येक को removeSpan के माध्यम से हटाएँ। वैकल्पिक रूप से, बिना स्पैन के एक नया SpannableString(text.toString()) बनाएँ। SpannableStringBuilder में clear() विधि है जो टेक्स्ट और स्पैन दोनों को हटाती है।
SpannableString EditText में काम करता है, लेकिन संपादन योग्य टेक्स्ट के लिए SpannableStringBuilder को प्राथमिकता दी जाती है जो Editable लागू करता है। EditText को परिवर्तनों को ट्रैक करने के लिए Editable इंटरफ़ेस की आवश्यकता होती है। यदि आप EditText में SpannableString पास करते हैं, तो टेक्स्ट स्टाइल के साथ प्रदर्शित होगा, लेकिन संपादन के दौरान Android इसे Editable में बदल देगा, जो कुछ स्पैन को रीसेट कर सकता है।
Jetpack Compose में, Android SDK स्पैन का सीधे उपयोग नहीं किया जाता है। इसके बजाय, Compose AnnotatedString प्रदान करता है, जो समान क्षमताओं वाला SpannableString का अपना समकक्ष है: व्यक्तिगत वर्ण स्टाइल के लिए SpanStyle और पैराग्राफ के लिए ParagraphStyle। SpannableString को AnnotatedString में बदलना स्पैन पर पुनरावृति के साथ buildAnnotatedString के माध्यम से संभव है।
एक क्लास बनाएँ जो CharacterStyle का विस्तार करे और updateDrawState(TextPaint tp) विधि को ओवरराइड करे। विधि के अंदर, TextPaint गुणों को संशोधित करें: रंग, स्ट्रोक चौड़ाई, प्रभाव। मीट्रिक परिवर्तनों के लिए, UpdateLayout या MetricAffectingSpan का उपयोग करें। कस्टम स्पैन अंतर्निहित स्पैन की तरह ही setSpan() के माध्यम से लागू किए जाते हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें