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

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 जैसे सभी एलिमेंट शामिल हैं.

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

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

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

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

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

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