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

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 ने अपने बच्चों को मेज़र कर लिया है, उनका साइज़ तय कर लिया है, और उन्हें प्लेस कर दिया है. इसलिए, अब वह अपना साइज़ और प्लेसमेंट तय कर सकता है.

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

परफ़ॉर्मेंस

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 में, कॉम्पोज़ेबल लेआउट को अलग-अलग स्क्रीन कॉन्फ़िगरेशन के हिसाब से ढालने के लिए, पहले से ही कुछ तरीके मौजूद होते हैं.

कंस्ट्रेंट

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

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