मॉडिफ़ायर लिखें

मॉडिफ़ायर की मदद से, कंपोज़ेबल को सजाने या बेहतर बनाया जा सकता है. मॉडिफ़ायर से आपको यह काम करने का मौका मिलता है इससे पता चलता है कि:

  • कंपोज़ेबल के साइज़, लेआउट, व्यवहार, और लुक में बदलाव करें
  • सुलभता के लेबल जैसी जानकारी जोड़ें
  • उपयोगकर्ता का इनपुट प्रोसेस करें
  • हाई-लेवल इंटरैक्शन जोड़ें. जैसे, एलिमेंट को क्लिक किया जा सकता है, स्क्रोल किया जा सकता है, खींचने और छोड़ने लायक या ज़ूम करने लायक

मॉडिफ़ायर, स्टैंडर्ड Kotlin ऑब्जेक्ट होते हैं. इनमें से किसी एक को कॉल करके मॉडिफ़ायर बनाएं Modifier क्लास फ़ंक्शन:

@Composable
private fun Greeting(name: String) {
    Column(modifier = Modifier.padding(24.dp)) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

रंगीन बैकग्राउंड के साथ टेक्स्ट की दो लाइन, जिसमें टेक्स्ट के चारों ओर पैडिंग (जगह) है.

इन फ़ंक्शन को एक साथ चेन करके, इन्हें कंपोज़ किया जा सकता है:

@Composable
private fun Greeting(name: String) {
    Column(
        modifier = Modifier
            .padding(24.dp)
            .fillMaxWidth()
    ) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

टेक्स्ट के पीछे रंगीन बैकग्राउंड अब डिवाइस की पूरी चौड़ाई को बढ़ाता है.

ऊपर दिए गए कोड में, एक साथ इस्तेमाल किए गए अलग-अलग मॉडिफ़ायर फ़ंक्शन पर ध्यान दें.

  • padding किसी एलिमेंट के आस-पास स्पेस रखता है.
  • fillMaxWidth कंपोज़ेबल फ़िल बनाता है, जिसकी वैल्यू इससे दी गई होती है इसकी पैरंट कंपनी है.

यह सबसे सही तरीका है कि सभी कंपोज़ेबल में modifier स्वीकार किया जाए पैरामीटर को कॉपी कर सकता है और उस मॉडिफ़ायर को यूज़र इंटरफ़ेस (यूआई) को उत्सर्जन करने वाले उसके पहले चाइल्ड को पास कर सकता है. ऐसा करने से आपका कोड को फिर से इस्तेमाल करने लायक बनाया जाता है. इस वजह से, इसके व्यवहार का अनुमान लगाने में मदद मिलती है और यह समझने में आसान हो जाता है. इसके लिए ज़्यादा जानकारी के लिए, Compose API के दिशा-निर्देश देखें. एलिमेंट, मॉडिफ़ायर पैरामीटर.

मॉडिफ़ायर का क्रम मायने रखता है

मॉडिफ़ायर फ़ंक्शन का क्रम अहम होता है. क्योंकि हर फ़ंक्शन बनाता है पिछले फ़ंक्शन से मिलने वाले Modifierमें बदलाव, क्रम आखिरी नतीजे पर असर डालता है. आइए इसका एक उदाहरण देखते हैं:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

किनारों के आस-पास की पैडिंग के साथ-साथ पूरा इलाका, क्लिक पर जवाब देता है

ऊपर दिए गए कोड में, आस-पास के एरिया के साथ-साथ पूरा इलाका क्लिक किया जा सकता है पैडिंग (जगह), क्योंकि padding मॉडिफ़ायर को clickable के बाद लागू किया गया है कार्रवाई बदलने वाली कुंजी. अगर कार्रवाई बदलने वाली कंपनियों के क्रम को उलटा जाता है, तो padding की जोड़ी गई स्पेस से ऐसा होता है उपयोगकर्ता के इनपुट पर प्रतिक्रिया न दें:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .padding(padding)
            .clickable(onClick = onClick)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

लेआउट के किनारे की पैडिंग (जगह), अब क्लिक के जवाब नहीं देती

पहले से मौजूद मॉडिफ़ायर

Jetpack Compose सुविधा में पहले से मौजूद मॉडिफ़ायर की सूची उपलब्ध कराता है. इससे आपको डेकोरेशन में मदद करने या कंपोज़ेबल को बेहतर बनाया. यहाँ कुछ सामान्य मॉडिफ़ायर दिए गए हैं जिनका इस्तेमाल करके, अपनी लेआउट.

padding और size

डिफ़ॉल्ट रूप से, Compose में मौजूद लेआउट की मदद से बच्चे अपने बच्चों को रैप करते हैं. हालांकि, size मॉडिफ़ायर का इस्तेमाल करके, साइज़ सेट किया जा सकता है:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(/*...*/)
        Column { /*...*/ }
    }
}

ध्यान दें कि अगर यह इन शर्तों के मुताबिक नहीं है, तो हो सकता है कि आपके बताए गए साइज़ को इस्तेमाल न किया जाए पाबंदियों की वजह से होता है. अगर आपको कंपोज़ेबल आने वाली सीमाओं पर ध्यान दिए बिना, साइज़ में बदलाव करने के लिए, requiredSize का इस्तेमाल करें कार्रवाई बदलने वाली कुंजी:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.requiredSize(150.dp)
        )
        Column { /*...*/ }
    }
}

चाइल्ड इमेज, अपने पैरंट की सीमाओं से बड़ी है

इस उदाहरण में, भले ही पैरंट height ने 100.dp पर सेट किया हो, फिर भी Image 150.dp होगी, क्योंकि requiredSize मॉडिफ़ायर प्राथमिकता.

अगर आपको लगता है कि कोई चाइल्ड लेआउट, पैरंट, fillMaxHeight मॉडिफ़ायर जोड़ें (Compose यह सुविधा भी देता है fillMaxSize और fillMaxWidth):

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.fillMaxHeight()
        )
        Column { /*...*/ }
    }
}

इमेज की ऊंचाई, इसकी पैरंट इमेज जितनी बड़ी है

किसी एलिमेंट के चारों ओर पैडिंग (जगह) जोड़ने के लिए, padding मॉडिफ़ायर सेट करें.

अगर आपको टेक्स्ट बेसलाइन के ऊपर पैडिंग (जगह) जोड़ना है, ताकि लेआउट के शीर्ष से बेसलाइन की विशेष दूरी के लिए, paddingFromBaseline मॉडिफ़ायर:

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(
                text = artist.name,
                modifier = Modifier.paddingFromBaseline(top = 50.dp)
            )
            Text(artist.lastSeenOnline)
        }
    }
}

ऊपर पैडिंग के साथ टेक्स्ट

ऑफ़सेट

लेआउट को उसकी मूल जगह के मुताबिक रखने के लिए, offset मॉडिफ़ायर दें और ऑफ़सेट को x और y ऐक्सिस पर सेट करें. ऑफ़सेट पॉज़िटिव और नॉन-पॉज़िटिव हो सकते हैं. इनके बीच अंतर padding और offset का मतलब है कि किसी कंपोज़ेबल में offset जोड़ने से इसकी माप बदलें:

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(artist.name)
            Text(
                text = artist.lastSeenOnline,
                modifier = Modifier.offset(x = 4.dp)
            )
        }
    }
}

टेक्स्ट को इसके पैरंट कंटेनर की दाईं ओर शिफ़्ट किया गया

offset मॉडिफ़ायर को लेआउट के निर्देश के मुताबिक हॉरिज़ॉन्टल तौर पर लागू किया जाता है. बाएं से दाएं के संदर्भ में, एक पॉज़िटिव offset एलिमेंट को दाएं से बाएं संदर्भ में होने पर, यह एलिमेंट को बाईं ओर शिफ़्ट कर देता है. अगर आपको लेआउट की दिशा पर विचार किए बिना ऑफ़सेट सेट करना है, तो absoluteOffset मॉडिफ़ायर, जिसमें पॉज़िटिव ऑफ़सेट वैल्यू हमेशा एलिमेंट को दाईं ओर.

offset मॉडिफ़ायर दो ओवरलोड देता है - offset जो ऑफ़सेट के हिसाब से पैरामीटर इस्तेमाल करता है और offset करता है, जो लैम्डा में लेता है. इनमें से हर एक का इस्तेमाल कब करें और कैसे ऑप्टिमाइज़ करें, परफ़ॉर्मेंस को बेहतर बनाने के लिए, परफ़ॉर्मेंस लिखें - लेख को जितना हो सके उतना टालें सेक्शन.

Compose में स्कोप की सुरक्षा

Compose में कुछ ऐसे मॉडिफ़ायर मौजूद हैं जिनका इस्तेमाल सिर्फ़ बच्चों पर लागू होने पर किया जा सकता है कुछ कंपोज़ेबल. Compose इसे कस्टम स्कोप की मदद से लागू करता है.

उदाहरण के लिए, अगर आपको किसी बच्चे को उसके माता-पिता जितना बड़ा बनाना है, तो Box Box के साइज़ पर असर पड़ रहा है, तो matchParentSize कार्रवाई बदलने वाली कुंजी. matchParentSize सिर्फ़ यहां उपलब्ध है BoxScope. इसलिए, इसका इस्तेमाल सिर्फ़ Box माता-पिता के बच्चे के लिए किया जा सकता है.

स्कोप सुरक्षा आपको ऐसे मॉडिफ़ायर जोड़ने से रोकती है जो किसी दूसरे डिवाइस में काम नहीं करेंगे कंपोज़ेबल और स्कोप शामिल किए गए हैं. साथ ही, यह ट्रायल और गड़बड़ी से जुड़े समय की बचत करता है.

स्कोप वाले मॉडिफ़ायर की मदद से, माता-पिता को पैरंट की कुछ जानकारी के बारे में बताया जाता है को यह जानकारी बच्चे के बारे में होनी चाहिए. आम तौर पर, इन्हें यह पैरंट डेटा मॉडिफ़ायर का इस्तेमाल करें. इन ईमेल पतों की जानकारी, ऐप्लिकेशन के सामान्य मकसद से अलग होती है मॉडिफ़ायर देते हैं, लेकिन इस्तेमाल के नज़रिए से देखें, तो ये अंतर कोई फ़र्क़ नहीं पड़ता.

matchParentSize, Box में है

जैसा कि ऊपर बताया गया है, अगर आपको चाइल्ड लेआउट को पैरंट के साइज़ के बराबर रखना है Box के साइज़ पर असर डाले बिना, Box, matchParentSize मॉडिफ़ायर का इस्तेमाल करें.

ध्यान दें कि matchParentSize सिर्फ़ Box दायरे में उपलब्ध है. इसका मतलब है कि यह सिर्फ़ Box कंपोज़ेबल के डायरेक्ट चाइल्ड पर लागू होता है.

नीचे दिए गए उदाहरण में, चाइल्ड Spacer अपना साइज़ अपने पैरंट Box से लेता है, और बड़े बच्चों, इस मामले में ArtistCard.

@Composable
fun MatchParentSizeComposable() {
    Box {
        Spacer(
            Modifier
                .matchParentSize()
                .background(Color.LightGray)
        )
        ArtistCard()
    }
}

कंटेनर को भरने वाला धूसर बैकग्राउंड

अगर matchParentSize के बजाय fillMaxSize का इस्तेमाल किया जाता, तो Spacer को माता-पिता के लिए उपलब्ध स्टोरेज की वजह से, माता-पिता को सभी उपलब्ध जगह को बड़ा करके भरें.

धूसर रंग का बैकग्राउंड, जिससे स्क्रीन दिख रही है

Row और Column में weight

जैसा कि आपने पिछले सेक्शन में पैडिंग और साइज़ होता है. डिफ़ॉल्ट रूप से, कंपोज़ेबल साइज़ को किस तरह का कॉन्टेंट फ़िलहाल चल रहा है. कंपोज़ेबल साइज़ को इस हिसाब से सेट किया जा सकता है कि साइज़ सिर्फ़ RowScope में उपलब्ध weight मॉडिफ़ायर का इस्तेमाल करने वाले माता-पिता, और ColumnScope.

चलिए, एक Row लेते हैं, जिसमें दो Box कंपोज़ेबल हैं. पहले बॉक्स को दूसरे बॉक्स की weight से दोगुनी वैल्यू दी जाती है, इसलिए इसे दो बार दिया जाता है: चौड़ाई. Row की चौड़ाई 210.dp है, इसलिए पहला Box 140.dp चौड़ा है और दूसरा है 70.dp:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.fillMaxWidth()
    ) {
        Image(
            /*...*/
            modifier = Modifier.weight(2f)
        )
        Column(
            modifier = Modifier.weight(1f)
        ) {
            /*...*/
        }
    }
}

इमेज की चौड़ाई, टेक्स्ट की चौड़ाई से दोगुनी है

मॉडिफ़ायर निकालना और दोबारा इस्तेमाल करना

सजावट के लिए अनेक संशोधकों को एक साथ जोड़ा जा सकता है या कंपोज़ेबल को बेहतर बनाया. यह चेन Modifier इंटरफ़ेस के ज़रिए बनाई गई है यह सिंगल Modifier.Elements की क्रम वाली और नहीं बदली जा सकने वाली सूची दिखाता है.

हर Modifier.Element एक व्यक्तिगत व्यवहार दिखाता है, जैसे कि लेआउट, ड्रॉइंग और ग्राफ़िक्स से जुड़े सभी व्यवहार, फ़ोकस, और सिमेंटिक्स से जुड़े व्यवहार शामिल होते हैं. डिवाइस इनपुट इवेंट भी होते हैं. उनका क्रम मायने रखता है: कार्रवाई बदलने वाली चीज़ें पहले जोड़ी गई वैल्यू को पहले लागू किया जाएगा.

कभी-कभी, कार्रवाई बदलने वाली एक ही चेन के इंस्टेंस का दोबारा इस्तेमाल करना फ़ायदेमंद हो सकता है अलग-अलग कंपोज़ेबल को वैरिएबल में एक्सट्रैक्ट करके और उन्हें एक साथ घुमाया जा सकता है बड़े दायरे होते हैं. इससे कोड को आसानी से पढ़ा जा सकता है या अपने ऐप्लिकेशन की परफ़ॉर्मेंस की कुछ वजहें हो सकती हैं:

  • बदलाव होने पर, मॉडिफ़ायर का फिर से आवंटन नहीं होगा उन कंपोज़ेबल के लिए जिनमें इसका इस्तेमाल किया जाता है
  • संशोधक शृंखलाएं बहुत लंबी और जटिल हो सकती हैं, इसलिए चेन में एक ही इंस्टेंस होने पर, वर्कलोड Compose के रनटाइम की ज़रूरत कम हो सकती है उनकी तुलना करते समय
  • इस एक्सट्रैक्शन से कोड को साफ़ रखने, एक जैसा काम करने, और रखरखाव को बढ़ावा मिलता है पूरे कोड बेस में

मॉडिफ़ायर को फिर से इस्तेमाल करने के सबसे सही तरीके

अपनी Modifier चेन बनाएं और एक से ज़्यादा जगहों पर उनका फिर से इस्तेमाल करने के लिए, उन्हें एक्सट्रैक्ट करें कंपोज़ेबल कॉम्पोनेंट. किसी मॉडिफ़ायर को सेव करना पूरी तरह से ठीक है, क्योंकि वे डेटा जैसे ऑब्जेक्ट होते हैं:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

बार-बार बदलने वाली स्थिति को देखते समय, मॉडिफ़ायर निकालना और दोबारा इस्तेमाल करना

कंपोज़ेबल में बार-बार बदलने वाले स्टेटस देखते समय, जैसे कि ऐनिमेशन राज्यों या scrollState के लिए, ऐसे कई फ़ॉर्मैट में बदलाव किए जा सकते हैं हो गया. इस मामले में, आपके मॉडिफ़ायर को हर बार बदलाव के बाद बांटा जाएगा हर फ़्रेम के लिए:

@Composable
fun LoadingWheelAnimation() {
    val animatedState = animateFloatAsState(/*...*/)

    LoadingWheel(
        // Creation and allocation of this modifier will happen on every frame of the animation!
        modifier = Modifier
            .padding(12.dp)
            .background(Color.Gray),
        animatedState = animatedState
    )
}

इसके बजाय, कार्रवाई बदलने वाली कुंजी का एक ही इंस्टेंस बनाया जा सकता है, एक्सट्रैक्ट किया जा सकता है, और दोबारा इस्तेमाल किया जा सकता है और इसे इस तरह कंपोज़ेबल में पास करें:

// Now, the allocation of the modifier happens here:
val reusableModifier = Modifier
    .padding(12.dp)
    .background(Color.Gray)

@Composable
fun LoadingWheelAnimation() {
    val animatedState = animateFloatAsState(/*...*/)

    LoadingWheel(
        // No allocation, as we're just reusing the same instance
        modifier = reusableModifier,
        animatedState = animatedState
    )
}

बिना स्कोप वाले मॉडिफ़ायर निकालना और उनका दोबारा इस्तेमाल करना

मॉडिफ़ायर को किसी चुनिंदा डाइमेंशन या कैटगरी के कंपोज़ेबल. अनस्कोप वाले मॉडिफ़ायर के मामले में, उन्हें आसानी से एक्सट्रैक्ट किया जा सकता है के अलावा अन्य कंपोज़ेबल में भी शामिल किया जा सकता है:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

@Composable
fun AuthorField() {
    HeaderText(
        // ...
        modifier = reusableModifier
    )
    SubtitleText(
        // ...
        modifier = reusableModifier
    )
}

लेज़ी लेआउट के साथ इस्तेमाल करने पर, यह काफ़ी मददगार हो सकता है. ज़्यादातर मामलों में, आप चाहते हैं कि आपके सभी, संभावित रूप से महत्वपूर्ण आइटम बिलकुल एक जैसे मॉडिफ़ायर:

val reusableItemModifier = Modifier
    .padding(bottom = 12.dp)
    .size(216.dp)
    .clip(CircleShape)

@Composable
private fun AuthorList(authors: List<Author>) {
    LazyColumn {
        items(authors) {
            AsyncImage(
                // ...
                modifier = reusableItemModifier,
            )
        }
    }
}

स्कोप वाले मॉडिफ़ायर निकालना और दोबारा इस्तेमाल करना

कुछ कंपोज़ेबल के दायरे में आने वाले मॉडिफ़ायर के साथ काम करते समय, उन्हें सबसे ज़्यादा संभावित लेवल तक एक्सट्रैक्ट करें और जहां भी सही हो वहां फिर से इस्तेमाल करें:

Column(/*...*/) {
    val reusableItemModifier = Modifier
        .padding(bottom = 12.dp)
        // Align Modifier.Element requires a ColumnScope
        .align(Alignment.CenterHorizontally)
        .weight(1f)
    Text1(
        modifier = reusableItemModifier,
        // ...
    )
    Text2(
        modifier = reusableItemModifier
        // ...
    )
    // ...
}

आपको सिर्फ़ एक्सट्रैक्ट किए गए, स्कोप वाले मॉडिफ़ायर को एक ही स्कोप वाले, डायरेक्ट चाइल्ड. इसके हिसाब से, स्कोप की सुरक्षा यह ज़रूरी क्यों है, इस बारे में ज़्यादा जानने के लिए लिखें:

Column(modifier = Modifier.fillMaxWidth()) {
    // Weight modifier is scoped to the Column composable
    val reusableItemModifier = Modifier.weight(1f)

    // Weight will be properly assigned here since this Text is a direct child of Column
    Text1(
        modifier = reusableItemModifier
        // ...
    )

    Box {
        Text2(
            // Weight won't do anything here since the Text composable is not a direct child of Column
            modifier = reusableItemModifier
            // ...
        )
    }
}

एक्सट्रैक्ट किए गए मॉडिफ़ायर की और चेन बनाना

आप .then() फ़ंक्शन:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

// Append to your reusableModifier
reusableModifier.clickable { /*...*/ }

// Append your reusableModifier
otherModifier.then(reusableModifier)

इस बात का ध्यान रखें कि मॉडिफ़ायर का क्रम अहम होता है!

ज़्यादा जानें

हमने मॉडिफ़ायर की पूरी सूची दी है. इसमें पैरामीटर और दायरों की जानकारी.

मॉडिफ़ायर इस्तेमाल करने के तरीके के बारे में ज़्यादा जानने के लिए, Compose कोडलैब में सामान्य लेआउट या अब Android डेटा स्टोर करने की जगह में.

कस्टम मॉडिफ़ायर और उन्हें बनाने के तरीके के बारे में ज़्यादा जानने के लिए, कस्टम लेआउट - लेआउट मॉडिफ़ायर का इस्तेमाल करना के बारे में जानकारी.