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

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

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

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

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

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

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

ऐप्लिकेशन बनाने की सुविधा देने वाले फ़ंक्शन की बुनियादी बातें

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

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

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

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

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

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 लेआउट में इंट्रिंसिक मेज़रमेंट लेख पढ़ें.

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

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

कंपोज़ेबल में बदलाव करने वाले मॉडिफ़ायर में बताए गए तरीके से, कंपोज़ेबल को बेहतर बनाने या उनमें बदलाव करने के लिए मॉडिफ़ायर का इस्तेमाल किया जा सकता है. लेआउट को पसंद के मुताबिक बनाने के लिए, मॉडिफ़ायर ज़रूरी होते हैं. उदाहरण के लिए, यहां हमने 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 जैसे सभी एलिमेंट दिए गए हैं.

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

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

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

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

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

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