लेआउट की बुनियादी बातें कंपोज़ करें

Jetpack Compose की मदद से, ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) डिज़ाइन करना और बनाना काफ़ी आसान हो जाता है. Compose, स्टेट को यूज़र इंटरफ़ेस (यूआई) एलिमेंट में बदलता है. इसके लिए, वह इन तरीकों का इस्तेमाल करता है:

  1. एलिमेंट का कंपोज़िशन
  2. एलिमेंट का लेआउट
  3. एलिमेंट की ड्रॉइंग

कंपोज़िशन, लेआउट, और ड्रॉइंग की मदद से, यूज़र इंटरफ़ेस (यूआई) में ट्रांसफ़ॉर्मिंग स्टेट को कंपोज़ करना

इस दस्तावेज़ में, एलिमेंट के लेआउट पर फ़ोकस किया गया है. इसमें, Compose के कुछ बिल्डिंग ब्लॉक के बारे में बताया गया है. इनकी मदद से, यूज़र इंटरफ़ेस (यूआई) एलिमेंट का लेआउट तैयार किया जा सकता है.

Compose में लेआउट के मकसद

लेआउट सिस्टम के Jetpack Compose के लागू करने के दो मुख्य मकसद हैं:

ऐप्लिकेशन बनाने की सुविधा के बुनियादी पहलू

ऐप्लिकेशन बनाने की सुविधा, Compose का बुनियादी बिल्डिंग ब्लॉक है. ऐप्लिकेशन बनाने की सुविधा, Unit एमिट करने वाला एक फ़ंक्शन है. यह आपके यूज़र इंटरफ़ेस (यूआई) के किसी हिस्से के बारे में बताता है. यह फ़ंक्शन कुछ इनपुट लेता है और स्क्रीन पर दिखने वाला कॉन्टेंट जनरेट करता है. कंपोज़ेबल के बारे में ज़्यादा जानने के लिए, Compose के मेंटल मॉडल का दस्तावेज़ देखें.

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

@Composable
fun ArtistCard() {
    Text("Alfred Sisley")
    Text("3 minutes ago")
}

अगर यह नहीं बताया जाता कि आपको उन्हें कैसे व्यवस्थित करना है, तो Compose, टेक्स्ट एलिमेंट को एक-दूसरे के ऊपर स्टैक कर देता है. इससे उन्हें पढ़ा नहीं जा सकता:

एक-दूसरे के ऊपर बनाए गए दो टेक्स्ट एलिमेंट, जिनकी वजह से टेक्स्ट पढ़ा नहीं जा सकता

Compose, यूज़र इंटरफ़ेस (यूआई) एलिमेंट को व्यवस्थित करने में आपकी मदद करने के लिए, इस्तेमाल के लिए तैयार लेआउट का कलेक्शन उपलब्ध कराता है. साथ ही, अपनी ज़रूरत के हिसाब से ज़्यादा खास लेआउट तय करना आसान बनाता है.

स्टैंडर्ड लेआउट कॉम्पोनेंट

कई मामलों में, Compose के स्टैंडर्ड लेआउट एलिमेंट का इस्तेमाल किया जा सकता है.

स्क्रीन पर आइटम को वर्टिकल तरीके से रखने के लिए, Column का इस्तेमाल करें.

@Composable
fun ArtistCardColumn() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

कॉलम लेआउट में व्यवस्थित किए गए दो टेक्स्ट एलिमेंट, ताकि टेक्स्ट को पढ़ा जा सके

इसी तरह, स्क्रीन पर आइटम को हॉरिज़ॉन्टल तरीके से रखने के लिए, Row का इस्तेमाल करें. Column और Row दोनों में, उनमें मौजूद एलिमेंट के अलाइनमेंट को कॉन्फ़िगर करने की सुविधा होती है.

@Composable
fun ArtistCardRow(artist: Artist) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column {
            Text(artist.name)
            Text(artist.lastSeenOnline)
        }
    }
}

इसमें ज़्यादा जटिल लेआउट दिखाया गया है. इसमें टेक्स्ट एलिमेंट के कॉलम के बगल में एक छोटा ग्राफ़िक है

एलिमेंट को एक-दूसरे के ऊपर रखने के लिए, Box का इस्तेमाल करें. Box में, उसमें मौजूद एलिमेंट के खास अलाइनमेंट को कॉन्फ़िगर करने की सुविधा भी होती है.

@Composable
fun ArtistAvatar(artist: Artist) {
    Box {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Icon(Icons.Filled.Check, contentDescription = "Check mark")
    }
}

इसमें एक-दूसरे के ऊपर रखे गए दो एलिमेंट दिखाए गए हैं

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

यह कॉलम, लाइन, और बॉक्स जैसे तीन लेआउट कंपोज़ेबल की तुलना करता है

Row में चाइल्ड की पोज़िशन सेट करने के लिए, horizontalArrangement और verticalAlignment आर्ग्युमेंट सेट करें. Column के लिए, verticalArrangement और horizontalAlignment आर्ग्युमेंट सेट करें:

@Composable
fun ArtistCardArrangement(artist: Artist) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.End
    ) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column { /*...*/ }
    }
}

आइटम दाईं ओर अलाइन किए गए हैं

लेआउट मॉडल

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

संक्षेप में, पैरंट नोड अपने चाइल्ड नोड से पहले मेज़र करते हैं, लेकिन उनका साइज़ और प्लेसमेंट, चाइल्ड नोड के बाद तय किया जाता है.

SearchResult फ़ंक्शन का उदाहरण देखें.

@Composable
fun SearchResult() {
    Row {
        Image(
            // ...
        )
        Column {
            Text(
                // ...
            )
            Text(
                // ...
            )
        }
    }
}

इस फ़ंक्शन से, यूज़र इंटरफ़ेस (यूआई) का यह ट्री मिलता है.

SearchResult
  Row
    Image
    Column
      Text
      Text

SearchResult के उदाहरण में, यूज़र इंटरफ़ेस (यूआई) ट्री का लेआउट इस क्रम में होता है:

  1. रूट नोड Row से मेज़र करने के लिए कहा जाता है.
  2. रूट नोड Row, अपने पहले चाइल्ड Image से मेज़र करने के लिए कहता है.
  3. Image एक लीफ़ नोड है. इसका मतलब है कि इसके कोई चाइल्ड नहीं हैं. इसलिए, यह साइज़ की जानकारी देता है और प्लेसमेंट के निर्देश वापस भेजता है.
  4. रूट नोड Row, अपने दूसरे चाइल्ड Column से मेज़र करने के लिए कहता है.
  5. Column नोड, अपने पहले Text चाइल्ड से मेज़र करने के लिए कहता है.
  6. पहला Text नोड एक लीफ़ नोड है. इसलिए, यह साइज़ की जानकारी देता है और प्लेसमेंट के निर्देश वापस भेजता है.
  7. Column नोड, अपने दूसरे Text चाइल्ड से मेज़र करने के लिए कहता है.
  8. दूसरा Text नोड एक लीफ़ नोड है. इसलिए, यह साइज़ की जानकारी देता है और प्लेसमेंट के निर्देश वापस भेजता है.
  9. अब Column नोड ने अपने चाइल्ड को मेज़र कर लिया है, उनका साइज़ तय कर लिया है, और उन्हें प्लेस कर दिया है. इसलिए, यह अपना साइज़ और प्लेसमेंट तय कर सकता है.
  10. अब रूट नोड Row ने अपने चाइल्ड को मेज़र कर लिया है, उनका साइज़ तय कर लिया है, और उन्हें प्लेस कर दिया है. इसलिए, यह अपना साइज़ और प्लेसमेंट तय कर सकता है.

सर्च नतीजों के यूज़र इंटरफ़ेस (यूआई) ट्री में मेज़रमेंट, साइज़, और प्लेसमेंट को क्रम से लगाना

परफ़ॉर्मेंस

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

अगर आपके लेआउट को किसी वजह से कई बार मेज़र करने की ज़रूरत है, तो Compose एक खास सिस्टम उपलब्ध कराता है. इसे इंट्रिंसिक मेज़रमेंट कहा जाता है. इस सुविधा के बारे में ज़्यादा जानने के लिए, Compose लेआउट में इंट्रिंसिक मेज़रमेंट लेख पढ़ें.

मेज़रमेंट और प्लेसमेंट, लेआउट पास के अलग-अलग सब-फ़ेज़ होते हैं. इसलिए, ऐसे बदलाव अलग से किए जा सकते हैं जिनका असर सिर्फ़ आइटम के प्लेसमेंट पर पड़ता है, न कि मेज़रमेंट पर.

अपने लेआउट में मॉडिफ़ायर का इस्तेमाल करना

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

@Composable
fun ArtistCardModifiers(
    artist: Artist,
    onClick: () -> Unit
) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ }
        Spacer(Modifier.size(padding))
        Card(
            elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        ) { /*...*/ }
    }
}

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

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

  • clickable की मदद से, कंपोज़ेबल उपयोगकर्ता के इनपुट पर प्रतिक्रिया करता है और रिपल दिखाता है.
  • padding की मदद से, किसी एलिमेंट के चारों ओर स्पेस जोड़ा जाता है.
  • fillMaxWidth की मदद से, कंपोज़ेबल अपने पैरंट से मिली ज़्यादा से ज़्यादा चौड़ाई को भरता है.
  • size() की मदद से, किसी एलिमेंट की पसंदीदा चौड़ाई और ऊंचाई तय की जाती है.

स्क्रोल किए जा सकने वाले लेआउट

स्क्रोल किए जा सकने वाले लेआउट के बारे में ज़्यादा जानने के लिए, Compose के जेस्चर का दस्तावेज़ देखें.

लिस्ट और लेज़ी लिस्ट के बारे में जानने के लिए, Compose की लिस्ट का दस्तावेज़ देखें.

रिस्पॉन्सिव लेआउट

लेआउट को अलग-अलग स्क्रीन ओरिएंटेशन और फ़ॉर्म फ़ैक्टर के साइज़ को ध्यान में रखकर डिज़ाइन किया जाना चाहिए. Compose, कंपोज़ेबल लेआउट को अलग-अलग स्क्रीन कॉन्फ़िगरेशन के हिसाब से ढालने के लिए, कुछ ऐसे मैकेनिज़्म उपलब्ध कराता है जिनका इस्तेमाल तुरंत किया जा सकता है.

कंस्ट्रेंट

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

@Composable
fun WithConstraintsComposable() {
    BoxWithConstraints {
        Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
    }
}

स्लॉट-आधारित लेआउट

Compose, Material Design पर आधारित कई कंपोज़ेबल उपलब्ध कराता है. इसके लिए, androidx.compose.material:material डिपेंडेंसी (Android Studio में Compose प्रोजेक्ट बनाते समय शामिल) का इस्तेमाल किया जाता है. इससे यूज़र इंटरफ़ेस (यूआई) बनाना आसान हो जाता है. Drawer, FloatingActionButton, और जैसे एलिमेंट उपलब्ध कराए जाते हैं.TopAppBar

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

Material Components ऐप्लिकेशन बार में उपलब्ध स्लॉट दिखाने वाला डायग्राम

कंपोज़ेबल आम तौर पर, content कंपोज़ेबल लैम्डा ( content: @Composable () -> Unit) लेते हैं. स्लॉट एपीआई, खास इस्तेमाल के लिए कई content पैरामीटर दिखाते हैं. उदाहरण के लिए, TopAppBar में title, navigationIcon, और actions के लिए कॉन्टेंट उपलब्ध कराया जा सकता है.

उदाहरण के लिए, Scaffold की मदद से, बुनियादी Material Design लेआउट स्ट्रक्चर वाला यूज़र इंटरफ़ेस (यूआई) लागू किया जा सकता है. Scaffoldटॉप-लेवल के सबसे सामान्य मटीरियल कॉम्पोनेंट के लिए स्लॉट उपलब्ध कराता है, जैसे, TopAppBar, BottomAppBar, FloatingActionButton, और Drawer. Scaffold का इस्तेमाल करके, यह पक्का करना आसान है कि ये कॉम्पोनेंट सही पोज़िशन पर हों और एक साथ सही तरीके से काम करें.

JetNews का सैंपल ऐप्लिकेशन, जिसमें कई एलिमेंट को व्यवस्थित करने के लिए Scaffold का इस्तेमाल किया गया है

@Composable
fun HomeScreen(/*...*/) {
    ModalNavigationDrawer(drawerContent = { /* ... */ }) {
        Scaffold(
            topBar = { /*...*/ }
        ) { contentPadding ->
            // ...
        }
    }
}