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

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

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

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

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

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

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