TextMeasurer Jetpack Compose का एक API है जो स्क्रीन पर वास्तविक रेंडरिंग से पहले टेक्स्ट के आयामों को मापने के लिए डिज़ाइन किया गया है। Android View में Paint.measureText के माध्यम से क्लासिक दृष्टिकोण के विपरीत, TextMeasurer शैली और बाधाओं को ध्यान में रखते हुए चौड़ाई, ऊंचाई और पंक्ति मीट्रिक प्राप्त करने का एक Compose-मूल तरीका प्रदान करता है। Android Developers Documentation (2025) के अनुसार, TextMeasurer का सक्रिय रूप से कस्टम Layout घटकों, एनिमेटेड लेबल और अनुकूली UI तत्वों में उपयोग किया जाता है जहां टेक्स्ट का आकार अन्य तत्वों की स्थिति को प्रभावित करता है।
मुख्य बातें
TextMeasurer androidx.compose.ui.text पैकेज का एक कार्यात्मक इंटरफ़ेस है जो Compose में टेक्स्ट को स्क्रीन पर वास्तव में रेंडर किए बिना मापने की अनुमति देता है। यह Compose टेक्स्ट इंजन का हिस्सा है और Paragraph API स्तर पर संचालित होता है, जो रेंडरिंग के लिए Skia का उपयोग करता है।
TextMeasurer का मुख्य उद्देश्य पूर्व-मापन है। Compose में, टेक्स्ट का आकार आमतौर पर Composable के Layout में रखे जाने के बाद निर्धारित किया जाता है। लेकिन ऐसे परिदृश्य हैं जहां आपको लेआउट से पहले टेक्स्ट की चौड़ाई जानने की आवश्यकता होती है — उदाहरण के लिए, यह तय करने के लिए कि स्ट्रिंग कंटेनर में फिट बैठती है या नहीं, या टेक्स्ट की लंबाई के आधार पर बटन के आकार की गणना करने के लिए।
TextMeasurer measure() विधि प्रदान करके इस समस्या को हल करता है, जो TextMeasureRequest (टेक्स्ट, शैली, बाधाएं) लेता है और TextLayoutResult (मीट्रिक, पंक्तियां, वर्ण) लौटाता है। यह डेवलपर को बिना एक फ्रेम की देरी के, सिंक्रोनस रूप से सभी टेक्स्ट डेटा प्राप्त करने की अनुमति देता है।
TextMeasurer का उपयोग करें जब टेक्स्ट का आकार पैरेंट घटक के आकार को प्रभावित करता है, एनिमेटेड टेक्स्ट ट्रांज़िशन बनाते समय, या कस्टम Layout लागू करते समय जहां टेक्स्ट अन्य तत्वों के साथ सह-अस्तित्व में है।
TextMeasurer API दो मुख्य संस्थाओं से बना है: rememberTextMeasurer() (इंस्टेंस बनाना) और measure() (मापन चलाना)। इंस्टेंस पूरे घटक जीवनचक्र के लिए एक बार बनाया जाता है और सभी मापों के लिए पुनः उपयोग किया जाता है।
val textMeasurer = rememberTextMeasurer()
val result = textMeasurer.measure(
text = "Hello, Compose!",
style = MaterialTheme.typography.bodyLarge,
constraints = Constraints(maxWidth = 200, maxHeight = 50)
)
// result.size.width, result.size.height, result.lineCount
constraints पैरामीटर अधिकतम चौड़ाई और ऊंचाई निर्धारित करता है जिसके भीतर टेक्स्ट फिट होना चाहिए। यदि टेक्स्ट चौड़ाई में फिट नहीं होता है, तो यह अगली पंक्ति में चला जाता है। मापन परिणाम में TextLayoutResult होता है, जो पंक्तियों की संख्या, प्रत्येक वर्ण की स्थिति, प्रत्येक पंक्ति की चौड़ाई और समग्र टेक्स्ट आकार प्रदान करता है।
TextMeasurer UI थ्रेड पर सिंक्रोनस रूप से काम करता है और पुनर्संयोजन को ट्रिगर नहीं करता है। हालांकि, विभिन्न शैलियों के साथ बार-बार टेक्स्ट मापन ओवरहेड बना सकता है — इसलिए इंस्टेंस remember के माध्यम से बनाया और पुनः उपयोग किया जाता है।
सबसे सरल परिदृश्य पैरेंट कंटेनर का आकार निर्धारित करने के लिए एकल-पंक्ति टेक्स्ट की चौड़ाई मापना है। उदाहरण के लिए, एक बटन जिसकी चौड़ाई लेबल की लंबाई पर निर्भर करती है।
val textMeasurer = rememberTextMeasurer()
var label by remember { mutableStateOf("Submit") }
val textResult = remember(label) {
textMeasurer.measure(
text = label,
style = MaterialTheme.typography.labelLarge,
constraints = Constraints(maxWidth = 1000, maxHeight = 100)
)
}
Box(
modifier = Modifier
.width(textResult.size.width.dp)
.height(40.dp)
.background(Color.Blue)
.clickable { onClick() }
) {
Text(text = label, style = MaterialTheme.typography.labelLarge)
}
इस उदाहरण में, remember(label) सुनिश्चित करता है कि मापन केवल तभी पुनः शुरू हो जब टेक्स्ट बदलता है। बाधाओं को बड़े maxWidth (1000) के साथ सेट किया गया है ताकि पंक्ति रैपिंग को रोका जा सके — वास्तविक बाधा टेक्स्ट की चौड़ाई के बराबर होगी। Box की चौड़ाई मापी गई टेक्स्ट चौड़ाई के बराबर सेट की गई है, जो “टेक्स्ट के आकार का बटन” प्रभाव देती है।
नोट: परिणाम से चौड़ाई को .dp के माध्यम से dp में कनवर्ट करने की आवश्यकता है, क्योंकि TextMeasurer आयाम पिक्सेल में लौटाता है, जबकि Modifier.width Dp की अपेक्षा करता है। सटीकता के लिए, density और LocalDensity.current का उपयोग करें।
बहु-पंक्ति टेक्स्ट के लिए, TextMeasurer न केवल कुल ऊंचाई बल्कि पंक्तियों की संख्या और पैराग्राफ के भीतर प्रत्येक वर्ण की स्थिति निर्धारित करने की अनुमति देता है। यह कस्टम टेक्स्ट फ़ील्ड, चैट या संपादक बनाते समय आवश्यक है।
बहु-पंक्ति टेक्स्ट के लिए मुख्य TextLayoutResult गुण: lineCount (पंक्तियों की संख्या), getLineTop(index) (पंक्ति प्रारंभ का Y-निर्देशांक), getLineBottom(index) (पंक्ति अंत का Y-निर्देशांक), getLineWidth(index) (पंक्ति की चौड़ाई)। इन्हें संयोजित करके, आप टेक्स्ट पंक्तियों के सापेक्ष इंटरफ़ेस तत्वों को सटीक रूप से स्थापित कर सकते हैं।
val textMeasurer = rememberTextMeasurer()
val result = textMeasurer.measure(
text = "Long multiline text that needs to be measured before layout",
style = MaterialTheme.typography.bodyMedium,
constraints = Constraints(maxWidth = 150, maxHeight = 300)
)
val linesCount = result.lineCount
val firstLineWidth = result.getLineWidth(0)
val totalHeight = result.size.height
getLineWidth(lineIndex) विधि निर्दिष्ट पंक्ति की चौड़ाई पिक्सेल में लौटाती है। यह maxWidth से कम हो सकती है यदि पंक्ति कंटेनर की सीमा तक नहीं पहुंचती है। प्रत्येक पंक्ति की चौड़ाई जानकर, आप मैन्युअल रूप से जस्टिफाई प्रभाव लागू कर सकते हैं या छोटी पंक्तियों के बगल में इनलाइन तत्व रख सकते हैं।
किसी विशिष्ट वर्ण की स्थिति प्राप्त करने के लिए, getBoundingBox(offset) का उपयोग करें, जो left, top, right, bottom निर्देशांक के साथ Rect लौटाता है। यह कस्टम टेक्स्ट फ़ील्ड में कर्सर स्थिति निर्धारण या एनिमेशन के साथ टेक्स्ट रेंज को हाइलाइट करने के लिए उपयोगी है।
TextMeasurer का सबसे शक्तिशाली अनुप्रयोग कस्टम Layout घटक हैं, जहां टेक्स्ट अन्य तत्वों के साथ सह-अस्तित्व में है और उनके आकार परस्पर निर्भर हैं। उदाहरण के लिए, एक “आइकन + टेक्स्ट” विजेट जहां आइकन पूरे ब्लॉक के बजाय टेक्स्ट की पहली पंक्ति के सापेक्ष केंद्रित होना चाहिए।
एक मानक Row में, आइकन पूरे Row की ऊंचाई से केंद्रित होता है, जो अप्राकृतिक दिखता है जब टेक्स्ट 3 पंक्तियां लेता है जबकि आइकन एक है। TextMeasurer के साथ, आप पहली पंक्ति को माप सकते हैं और आइकन को उसके साथ सटीक रूप से संरेखित कर सकते हैं।
val textMeasurer = rememberTextMeasurer()
Layout(
content = {
Icon(imageVector = Icons.Default.Star, contentDescription = null)
Text(text = "Multi-line text here")
},
measurePolicy = { measurables, constraints ->
val textMeasurable = measurables[1]
val textPlaceable = textMeasurable.measure(constraints)
val iconPlaceable = measurables[0].measure(constraints)
val firstLineHeight = textMeasurer.measure(
text = "Sample",
style = MaterialTheme.typography.bodyMedium,
constraints = Constraints(maxWidth = 2000, maxHeight = 100)
).size.height
layout(width = textPlaceable.width + iconPlaceable.width,
height = maxOf(textPlaceable.height, iconPlaceable.height)) {
iconPlaceable.placeRelative(0, (firstLineHeight - iconPlaceable.height) / 2)
textPlaceable.placeRelative(iconPlaceable.width, 0)
}
}
)
इस उदाहरण में, TextMeasurer के माध्यम से पहली पंक्ति का मापन आइकन की स्थिति निर्धारित करता है। TextMeasurer के बिना, आइकन बहु-पंक्ति टेक्स्ट की पूरी ऊंचाई से केंद्रित होगा, जो दृश्य रूप से गलत है। इस पैटर्न का व्यापक रूप से चैट, संपर्क सूचियों और सूचना कार्ड में उपयोग किया जाता है।
TextMeasurer एक सिंक्रोनस API है जो UI थ्रेड पर चलता है। इसका अत्यधिक उपयोग फ्रेम ड्रॉप का कारण बन सकता है, विशेष रूप से कमजोर उपकरणों पर बड़ी टेक्स्ट मात्रा मापते समय।
पहला नियम — परिणाम को कैश करें. हमेशा measure() कॉल को टेक्स्ट और शैली निर्भरता के साथ remember में लपेटें। CompositionLocal के अंदर या हॉट पुनर्संयोजन पथों में measure() को कभी न कॉल करें।
दूसरा नियम — maxWidth और maxHeight को सीमित करें. यदि आप maxWidth = Constraints.Infinity सेट करते हैं, तो TextMeasurer पंक्तियों को रैप नहीं कर पाएगा और टेक्स्ट स्क्रीन से बाहर चला जाएगा। हमेशा यथार्थवादी बाधाएं पास करें, विशेष रूप से बहु-पंक्ति टेक्स्ट के लिए।
तीसरा नियम — समान मापदंडों के साथ बार-बार मापन से बचें. यदि टेक्स्ट और शैली नहीं बदली है, तो measure() का परिणाम वही होगा। अतुल्यकालिक परिदृश्यों के लिए मापन को Deferred या LaunchedEffect के साथ संयोजित करें।
अक्सर पूछे जाने वाले प्रश्न
TextMeasurer रेंडरिंग से पहले टेक्स्ट मापता है, जबकि onSizeChanged बाद में मापता है। TextMeasurer की आवश्यकता तब होती है जब टेक्स्ट का आकार पैरेंट लेआउट को प्रभावित करता है; onSizeChanged संयोजन के बाद प्रतिक्रियाशील तर्क के लिए काम करता है।
हां, TextMeasurer.measure() AnnotatedString को स्वीकार करता है, जिसमें इनलाइन शैलियों, लिंक और रंगों के साथ SpannableString शामिल है। मापन के दौरान सभी स्पैन को ध्यान में रखा जाता है।
TextMeasurer Skia रेंडरिंग स्तर पर काम करता है, जहां सभी आयाम पिक्सेल में हैं। LocalDensity.current के माध्यम से कनवर्ट करें: density.run { width.toDp() }.
TextMeasurer कस्टम फ़ॉन्ट लोड होने तक FontFamily.Default का उपयोग करता है। सटीक मापन के लिए, FontResource के माध्यम से फ़ॉन्ट लोड होने की प्रतीक्षा करें और async/await का उपयोग करें।
प्रत्येक LazyColumn आइटम में टेक्स्ट मापना कमजोर उपकरणों पर FPS कम कर सकता है। अनुकूलन: remember के माध्यम से परिणाम कैश करें और टेक्स्ट आकार सीमित करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें