Compose का एक नियम यह है कि आपको अपने बच्चों को सिर्फ़ एक बार मेज़र करना चाहिए. अगर बच्चों को दो बार मेज़र किया जाता है, तो रनटाइम एक्सप्शन दिखता है. हालांकि, कभी-कभी ऐसा होता है कि बच्चों की परफ़ॉर्मेंस का आकलन करने से पहले, आपको उनके बारे में कुछ जानकारी चाहिए.
Intrinsics की मदद से, बच्चों की परफ़ॉर्मेंस का आकलन करने से पहले ही उनके बारे में जानकारी हासिल की जा सकती है.
किसी कॉम्पोज़ेबल के लिए, intrinsicWidth
या intrinsicHeight
का अनुरोध किया जा सकता है:
(min|max)IntrinsicWidth
: इस चौड़ाई को देखते हुए, अपने कॉन्टेंट को पेंट करने के लिए कम से कम/ज़्यादा से ज़्यादा चौड़ाई कितनी होनी चाहिए?(min|max)IntrinsicHeight
: इस ऊंचाई को देखते हुए, अपने कॉन्टेंट को पेंट करने के लिए कम से कम/ज़्यादा से ज़्यादा ऊंचाई कितनी होनी चाहिए?
उदाहरण के लिए, अगर अनगिनत height
वाले Text
के minIntrinsicHeight
से पूछा जाता है, तो यह Text
का height
दिखाएगा. ऐसा तब होगा, जैसे टेक्स्ट किसी एक लाइन में बनाया गया हो.
Intrinsics का इस्तेमाल
मान लें कि हमें एक ऐसा कॉम्पोज़ेबल बनाना है जो स्क्रीन पर दो टेक्स्ट दिखाता हो और उन्हें इस तरह से अलग करता हो:
हम यह कैसे कर सकते हैं? हमारे पास Row
में दो Text
हो सकते हैं, जो ज़्यादा से ज़्यादा बड़े हो सकते हैं और बीच में एक Divider
हो सकता है. हम चाहते हैं कि Divider
सबसे ऊंचे Text
के बराबर और सबसे पतला (width = 1.dp
) हो.
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) HorizontalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
इसकी झलक देखने पर, हमें पता चलता है कि Divider
पूरी स्क्रीन पर बड़ा हो जाता है और हम यह नहीं चाहते:
ऐसा इसलिए होता है, क्योंकि Row
हर बच्चे की ऊंचाई को अलग-अलग मेज़र करता है. साथ ही, Text
की सीमा तय करने के लिए, Text
की ऊंचाई का इस्तेमाल नहीं किया जा सकता.Divider
हम चाहते हैं कि Divider
, उपलब्ध जगह को तय की गई ऊंचाई के हिसाब से भर दे. इसके लिए, हम
height(IntrinsicSize.Min)
मॉडिफ़ायर का इस्तेमाल कर सकते हैं .
height(IntrinsicSize.Min)
अपने बच्चों को उनकी कम से कम प्राकृतिक ऊंचाई के बराबर ऊंचा करने के लिए मजबूर करता है. यह फ़ंक्शन बार-बार चलने वाला है, इसलिए यह Row
और उसके minIntrinsicHeight
बच्चों की क्वेरी करेगा.
इसे हमारे कोड में लागू करने पर, यह उम्मीद के मुताबिक काम करेगा:
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier.height(IntrinsicSize.Min)) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) HorizontalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } } // @Preview @Composable fun TwoTextsPreview() { MaterialTheme { Surface { TwoTexts(text1 = "Hi", text2 = "there") } } }
झलक के साथ:
Row
कॉम्पोज़ेबल का minIntrinsicHeight
, उसके बच्चों का ज़्यादा से ज़्यादा
minIntrinsicHeight
होगा. Divider
एलिमेंट का minIntrinsicHeight
0 है, क्योंकि अगर कोई कंस्ट्रेंट नहीं किया गया है, तो यह स्पेस नहीं लेता है. Text
minIntrinsicHeight
, खास width
वाले टेक्स्ट में से एक होगा. इसलिए, Row
एलिमेंट का height
कंस्ट्रेंट, Text
का ज़्यादा से ज़्यादा minIntrinsicHeight
होगा. इसके बाद, Divider
अपने height
को Row
की तय की गई height
सीमा तक बढ़ा देगा.
पसंद के मुताबिक लेआउट में इंट्रिनिक
कस्टम Layout
या layout
मॉडिफ़ायर बनाते समय, अनुमान के आधार पर इनट्रिन्सिक मेज़रमेंट अपने-आप कैलकुलेट हो जाते हैं. इसलिए, हो सकता है कि सभी लेआउट के लिए कैलकुलेशन सही न हो. ये एपीआई, इन डिफ़ॉल्ट वैल्यू को बदलने के विकल्प देते हैं.
अपने कस्टम Layout
के अंदरूनी माप तय करने के लिए, MeasurePolicy
इंटरफ़ेस को बनाते समय minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
, और maxIntrinsicHeight
को बदलें.
@Composable fun MyCustomComposable( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( content = content, modifier = modifier, measurePolicy = object : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. } ) }
अपना कस्टम layout
मॉडिफ़ायर बनाते समय, LayoutModifier
इंटरफ़ेस में उससे जुड़े तरीकों को बदलें.
fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier { override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. }
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक टेक्स्ट दिखता है
- कस्टम लेआउट {:#custom-layouts }
- Jetpack Compose में अलाइनमेंट लाइनें
- Jetpack Compose के चरण