Compose के लेआउट में इंट्रिंसिक मेज़रमेंट

Compose का एक नियम यह भी है कि आपको अपने बच्चों का आकलन सिर्फ़ एक बार करना चाहिए; बच्चों को दो बार मापने से रनटाइम अपवाद मिलता है. हालांकि, कई बार ऐसा भी होता है भी नहीं है.

Intrinsics की मदद से, बच्चों को मेज़र करने से पहले ही उनसे क्वेरी करने की सुविधा मिलती है.

किसी कंपोज़ेबल में intrinsicWidth या intrinsicHeight मांगा जा सकता है:

  • (min|max)IntrinsicWidth: इस चौड़ाई को देखते हुए, कम से कम/ज़्यादा से ज़्यादा कितना हो सकता है क्या आप अपने कॉन्टेंट को सही तरीके से पेंट कर सकते हैं?
  • (min|max)IntrinsicHeight: इस ऊंचाई को देखते हुए, कम से कम/ज़्यादा से ज़्यादा कितना हो सकता है की ऊंचाई के हिसाब से अपने कॉन्टेंट को सही ढंग से पेंट करने में मदद कर सकते हैं?

उदाहरण के लिए, अगर अनगिनत संख्या वाले Text के minIntrinsicHeight से पूछा जाए height है, तो यह Text का height ऐसे दिखाएगा जैसे टेक्स्ट को एकल पंक्ति.

इंट्रेंस का इस्तेमाल करने का तरीका

मान लें कि हम एक ऐसा कंपोज़ेबल बनाना चाहते हैं जो स्क्रीन को इस तरह से डिवाइडर से अलग करें:

टेक्स्ट के दो एलिमेंट अगल-बगल में हैं और उनके बीच में वर्टिकल डिवाइडर है

हम यह कैसे कर सकते हैं? हमारे पास दो Text के साथ एक Row हो सकता है, जो इस तरह बड़ा होता है स्क्रीन के बीच में एक 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
        )
        Divider(
            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 हर बच्चे की लंबाई और उम्र को अलग-अलग मापता है Divider को सीमित करने के लिए, Text का इस्तेमाल नहीं किया जा सकता. हम चाहते हैं कि 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
        )
        Divider(
            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 के अंदरूनी माप बताने के लिए, minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth को बदलें और maxIntrinsicHeight MeasurePolicy उसे बनाते समय उसका इस्तेमाल किया जा सकता है.

@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.
}