Compose for Wear OS का इस्तेमाल करके पेजिंग करना

पेजिंग की सुविधा की मदद से, Wear OS डिवाइसों पर लोग अलग-अलग फ़ुल-स्क्रीन पेजों के बीच हॉरिज़ॉन्टल या वर्टिकल स्वाइप कर सकते हैं. इसके इस्तेमाल के सामान्य उदाहरणों में, कसरत से जुड़े ऐप्लिकेशन में कसरत की मेट्रिक और मीडिया कंट्रोल के बीच स्वाइप करना या एक से ज़्यादा पेज वाले फ़्लो से आगे बढ़ना शामिल है.

Compose for Wear OS Material 3 में, HorizontalPagerScaffold और VerticalPagerScaffold, पेज लेआउट को व्यवस्थित करते हैं. साथ ही, TimeText की मदद से, पेज इंडिकेटर को अपने-आप पोज़िशन करते हैं और ट्रांज़िशन मैनेज करते हैं. हर पेज को AnimatedPage कंपोज़ेबल में रैप किया जाता है. इससे, राउंड डिसप्ले पर पेजों के ट्रांज़िशन के दौरान, स्केलिंग, राउंड कॉर्नर मॉर्फ़िंग, और स्क्रिम इफ़ेक्ट लागू होते हैं.

इस ऐनिमेशन में दिखाया गया है कि हॉरिज़ॉन्टल स्वाइप के दौरान, HorizontalPagerScaffold और AnimatedPage पेजों को कैसे स्केल करते हैं और उनमें ऐनिमेशन कैसे जोड़ते हैं:

पेजिंग के लिए स्कैफ़ोल्ड हैरारकी

Material 3 में पेज वाले स्क्रीन लेआउट डिज़ाइन करते समय, कॉम्पोनेंट के इस क्रम का इस्तेमाल करें. चाहे स्वाइप करने के लिए बाएं या दाएं (HorizontalPager) या ऊपर या नीचे (VerticalPager) का इस्तेमाल किया जा रहा हो. कॉम्पोनेंट का क्रम, आउटर कंटेनर से लेकर अंदर के कॉन्टेंट तक होना चाहिए:

  1. AppScaffold: यह आपके ऐप्लिकेशन का सबसे बाहरी कंटेनर होता है. इसका इस्तेमाल सिर्फ़ एक बार किया जा सकता है. यह ग्लोबल TimeText ओवरले को ऐंकर करता है, ताकि पेज ट्रांज़िशन और स्वाइप करके खारिज करने के जेस्चर के दौरान, घड़ी स्क्रीन पर सबसे ऊपर स्थिर रहे.
  2. HorizontalPagerScaffold या VerticalPagerScaffold: इन्हें पेजर लेवल पर AppScaffold के अंदर रखा जाता है. यह TimeText और HorizontalPageIndicator या VerticalPageIndicator के बीच ट्रांज़िशन को मैनेज करता है.
  3. HorizontalPager या VerticalPager: यह फ़ाउंडेशन पेजर कंटेनर है. यह स्वाइप जेस्चर, फ़्लिंग फ़िज़िक्स, और रोटरी इनपुट स्नैपिंग को मैनेज करता है. इसके लिए, शेयर किए गए PagerState का इस्तेमाल किया जाता है.
  4. AnimatedPage: इसे पेजर के पेज कॉन्टेंट लैंबडा में रखा जाता है. यह हर पेज को रैप करता है, ताकि पेज के ऑफ़सेटPagerState के आधार पर, Material 3 ट्रांज़िशन ऐनिमेशन (स्केलिंग और स्क्रिम इफ़ेक्ट) लागू किए जा सकें.
  5. ScreenScaffold: इसे हर पेज के लिए, AnimatedPage अंदर रखा जाता है. हर पेज में, वर्टिकल तौर पर स्क्रोल की जा सकने वाली अपनी सूची (जैसे कि TransformingLazyColumn) या अपना EdgeButton हो सकता है. इसलिए, हर पेज में ScreenScaffold को नेस्ट करने से यह पक्का होता है कि वर्टिकल स्क्रोल इंडिकेटर, एज बटन, और contentPadding उसी पेज से जुड़े हों और उसके साथ आसानी से ऐनिमेट हों.
AppScaffold (1 per app: anchors global TimeText)
 └── HorizontalPagerScaffold / VerticalPagerScaffold (manages PageIndicator)
      └── HorizontalPager / VerticalPager (manages PagerState & fling behavior)
           └── AnimatedPage (applies scaling & scrim transitions per page)
                └── ScreenScaffold (1 per page: ScrollIndicator & EdgeButton)
                     └── Page Content (Column or TransformingLazyColumn)

हॉरिज़ॉन्टल पेजर लागू करना

Material 3 में हॉरिज़ॉन्टल पेजर लागू करने के लिए, अपने ऐप्लिकेशन के AppScaffold में HorizontalPagerScaffold, HorizontalPager, AnimatedPage, और ScreenScaffold को नेस्ट करें.

PagerScaffoldDefaults.snapWithSpringFlingBehavior का इस्तेमाल करके, flingBehavior के लिए Material 3 स्प्रिंग मोशन फ़िज़िक्स और रिस्पॉन्सिव पेज स्नैपिंग (HighSnapPositionalThreshold) लागू करें. डिफ़ॉल्ट रूप से, HorizontalPager रोटरी पेज स्क्रोलिंग (rotaryScrollableBehavior = null) को बंद कर देता है. इससे रोटेटिंग क्राउन या बेज़ल इनपुट का इस्तेमाल करके, ऐक्टिव पेज में मौजूद वर्टिकल सूचियों (जैसे कि TransformingLazyColumn) को स्क्रोल किया जा सकता है.

यहां HorizontalPagerScaffold को पूरी तरह से सेट अप करने का एक उदाहरण दिया गया है:

@Composable
fun HorizontalPagerScaffoldSample(navigateBack: () -> Unit) {
    AppScaffold {
        val pagerState = rememberPagerState(pageCount = { 10 })

        HorizontalPagerScaffold(pagerState = pagerState) {
            HorizontalPager(
                state = pagerState,
                flingBehavior =
                    PagerScaffoldDefaults.snapWithSpringFlingBehavior(
                        state = pagerState
                    ),
            ) { page ->
                AnimatedPage(pageIndex = page, pagerState = pagerState) {
                    ScreenScaffold {
                        Column(
                            modifier = Modifier.fillMaxSize(),
                            horizontalAlignment = Alignment.CenterHorizontally,
                            verticalArrangement = Arrangement.Center,
                        ) {
                            Text(text = "Page #$page")
                            Spacer(modifier = Modifier.height(8.dp))
                            Text(text = "Swipe left and right")
                            if (page == 0) {
                                Spacer(modifier = Modifier.height(16.dp))
                                Button(onClick = navigateBack) { Text("Exit") }
                            }
                        }
                    }
                }
            }
        }
    }
}

अगर आपके हॉरिज़ॉन्टल पेजर में मौजूद किसी पेज में TransformingLazyColumn शामिल है, तो उस पेज के स्कोप में एक अलग rememberTransformingLazyColumnState() बनाएं. इसके बाद, उसे इनर ScreenScaffold और TransformingLazyColumn को पास करें:

AppScaffold {
    val pagerState = rememberPagerState(pageCount = { 10 })

    HorizontalPagerScaffold(pagerState = pagerState) {
        HorizontalPager(
            state = pagerState,
            flingBehavior =
                PagerScaffoldDefaults.snapWithSpringFlingBehavior(
                    state = pagerState
                ),
        ) { page ->
            AnimatedPage(pageIndex = page, pagerState = pagerState) {
                val columnState = rememberTransformingLazyColumnState()
                val transformationSpec = rememberTransformationSpec()

                ScreenScaffold(
                    scrollState = columnState,
                ) { contentPadding ->
                    TransformingLazyColumn(
                        state = columnState,
                        contentPadding = contentPadding,
                    ) {
                        item {
                            ListHeader(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .transformedHeight(this, transformationSpec)
                                    .minimumVerticalContentPadding(
                                        ListHeaderDefaults.minimumTopListContentPadding
                                    ),
                                transformation = SurfaceTransformation(transformationSpec),
                            ) {
                                Text(text = "Pager sample")
                            }
                        }
                        item {
                            Card(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .transformedHeight(this, transformationSpec)
                                    .minimumVerticalContentPadding(
                                        CardDefaults.minimumVerticalListContentPadding
                                    ),
                                transformation = SurfaceTransformation(transformationSpec),
                            ) {
                                if (page == 0) {
                                    Text(text = "Page #$page. Swipe right")
                                } else {
                                    Text(text = "Page #$page. Swipe left and right")
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

वर्टिकल पेजर लागू करना

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

HorizontalPager के उलट, VerticalPager रोटरी पेज स्नैपिंग को डिफ़ॉल्ट रूप से चालू करता है (RotaryScrollableDefaults.snapBehavior(state)). PagerScaffoldDefaults.snapWithSpringFlingBehavior को flingBehavior पर पास करें और हर पेज को AnimatedPage और ScreenScaffold में रैप करें:

@Composable
fun VerticalPagerScaffoldSample() {
    AppScaffold {
        val pagerState = rememberPagerState(pageCount = { 10 })

        VerticalPagerScaffold(pagerState = pagerState) {
            VerticalPager(
                state = pagerState,
                flingBehavior =
                    PagerScaffoldDefaults.snapWithSpringFlingBehavior(
                        state = pagerState
                    ),
            ) { page ->
                AnimatedPage(pageIndex = page, pagerState = pagerState) {
                    ScreenScaffold {
                        Column(
                            modifier = Modifier.fillMaxSize(),
                            horizontalAlignment = Alignment.CenterHorizontally,
                            verticalArrangement = Arrangement.Center,
                        ) {
                            Text(text = "Page #$page")
                            Spacer(modifier = Modifier.height(8.dp))
                            Text(text = "Swipe up and down")
                        }
                    }
                }
            }
        }
    }
}

पेजर के व्यवहार को पसंद के मुताबिक बनाना

अपने ऐप्लिकेशन के साथ इंटरैक्ट करने की ज़रूरतों के हिसाब से, HorizontalPagerScaffold और VerticalPagerScaffold की स्नैपिंग की संवेदनशीलता को पसंद के मुताबिक बनाया जा सकता है.

कसरत के दौरान स्नैप की सेंसिटिविटी अडजस्ट करना

वर्कआउट या ऐसी गतिविधियों के दौरान जिनमें उपयोगकर्ता के हाथ का मूवमेंट ज़्यादा होता है, गलती से स्क्रीन छूने या डिजिटल क्राउन के थोड़ा घूमने से पेज बदल सकते हैं. इन स्क्रीन के लिए, कम स्नैप सेंसिटिविटी के साथ पेजर को कॉन्फ़िगर करें:

  • PagerDefaults.snapFlingBehavior को maxFlingPages = 0 और snapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold के साथ पास करें, ताकि पेज पलटने के लिए स्क्रीन के ज़्यादातर हिस्से पर जान-बूझकर खींचने और छोड़ने की ज़रूरत पड़े.
  • अगर आपने रोटरी पेज स्नैपिंग की सुविधा चालू की है, तो snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivity में RotaryScrollableDefaults.snapBehavior को सेट करें, ताकि अगले पेज पर स्नैप करने से पहले ज़्यादा रोटेशन की ज़रूरत पड़े.
@Composable
fun HorizontalPagerScaffoldWithLowSensitivitySample(navigateBack: () -> Unit) {
    AppScaffold {
        val pagerState = rememberPagerState(pageCount = { 3 })

        HorizontalPagerScaffold(pagerState = pagerState) {
            HorizontalPager(
                state = pagerState,
                flingBehavior =
                    PagerDefaults.snapFlingBehavior(
                        state = pagerState,
                        maxFlingPages = 0,
                        snapPositionalThreshold =
                            PagerScaffoldDefaults.LowSnapPositionalThreshold,
                    ),
                rotaryScrollableBehavior =
                    RotaryScrollableDefaults.snapBehavior(
                        pagerState = pagerState,
                        snapSensitivity =
                            RotaryScrollableDefaults.LowSnapSensitivity,
                    ),
            ) { page ->
                AnimatedPage(pageIndex = page, pagerState = pagerState) {
                    ScreenScaffold {
                        // Page content
                    }
                }
            }
        }
    }
}

सैंपल के तौर पर लागू किए गए पूरे कोड देखने के लिए, android/snippets रिपॉज़िटरी में Pager.kt और AndroidX रिपॉज़िटरी में PagerScaffoldSample.kt देखें.