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

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 में, मटीरियल डिज़ाइन पर आधारित कई तरह के कंपोज़ेबल उपलब्ध हैं. इनमें androidx.compose.material:material डिपेंडेंसी (Android Studio में Compose प्रोजेक्ट बनाते समय शामिल की जाती है) भी शामिल है. इससे यूज़र इंटरफ़ेस (यूआई) बनाना आसान हो जाता है. Drawer, FloatingActionButton, और TopAppBar जैसे एलिमेंट उपलब्ध कराए गए हैं.

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

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

कंपोज़ेबल आम तौर पर, 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 ->
            // ...
        }
    }
}