कॉन्टेंट को दाएं-बाएं या ऊपर-नीचे स्वाइप करने के लिए, HorizontalPager और VerticalPager कंपोज़ेबल का इस्तेमाल किया जा सकता है. इनके फ़ंक्शन, व्यू सिस्टम में मौजूद ViewPager के फ़ंक्शन जैसे ही होते हैं. डिफ़ॉल्ट रूप से, HorizontalPager पूरी स्क्रीन की चौड़ाई और VerticalPager पूरी स्क्रीन की ऊंचाई लेता है. पेजर, एक बार में सिर्फ़ एक पेज को फ़्लिंग करते हैं. इन सभी डिफ़ॉल्ट सेटिंग को कॉन्फ़िगर किया जा सकता है.
HorizontalPager
दाएं और बाएं स्वाइप करके स्क्रोल करने वाला पेजर बनाने के लिए, HorizontalPager का इस्तेमाल करें:
HorizontalPager
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
VerticalPager
ऊपर और नीचे स्वाइप करके स्क्रोल करने वाला पेजर बनाने के लिए, VerticalPager का इस्तेमाल करें:
VerticalPager
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
लेज़ी क्रिएशन
HorizontalPager और VerticalPager, दोनों में मौजूद पेजों को ज़रूरत पड़ने पर, लेज़ी कंपोज़
किया जाता है और लेआउट किया जाता है. जब उपयोगकर्ता पेजों के बीच स्क्रोल करता है, तो कंपोज़ेबल उन पेजों को हटा देता है जिनकी अब ज़रूरत नहीं होती.
स्क्रीन से बाहर मौजूद ज़्यादा पेज लोड करना
डिफ़ॉल्ट रूप से, पेजर सिर्फ़ स्क्रीन पर दिखने वाले पेजों को लोड करता है. स्क्रीन से बाहर मौजूद ज़्यादा पेज लोड करने के लिए, beyondBoundsPageCount को शून्य से ज़्यादा वैल्यू पर सेट करें.
पेजर में किसी आइटम पर स्क्रोल करना
पेजर में किसी खास पेज पर स्क्रोल करने के लिए, PagerState ऑब्जेक्ट
बनाने के लिए rememberPagerState() का इस्तेमाल करें. इसके बाद, इसे पेजर के state पैरामीटर के तौर पर
पास करें. `
CoroutineScope` में, इस स्टेट पर `PagerState#scrollToPage()` को कॉल किया जा सकता है:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.scrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
अगर आपको पेज पर ऐनिमेशन दिखाना है, तो
PagerState#animateScrollToPage() फ़ंक्शन का इस्तेमाल करें:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.animateScrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
पेज की स्थिति में होने वाले बदलावों के बारे में सूचना पाना
PagerState में पेजों के बारे में जानकारी देने वाली तीन प्रॉपर्टी होती हैं:
currentPage, settledPage, और targetPage.
currentPage: स्नैप पोज़िशन के सबसे पास वाला पेज. डिफ़ॉल्ट रूप से, स्नैप पोज़िशन लेआउट की शुरुआत में होती है.settledPage: वह पेज नंबर जब कोई ऐनिमेशन या स्क्रोलिंग नहीं चल रही होती. यहcurrentPageप्रॉपर्टी से अलग है. ऐसा इसलिए, क्योंकि अगर पेज स्नैप पोज़िशन के काफ़ी पास है, तोcurrentPageतुरंत अपडेट हो जाता है. हालांकि,settledPageतब तक वही रहता है, जब तक सभी ऐनिमेशन पूरे नहीं हो जाते.targetPage: स्क्रोलिंग मूवमेंट के लिए, सुझाई गई स्टॉप पोज़िशन.
snapshotFlow फ़ंक्शन का इस्तेमाल करके, इन वैरिएबल में होने वाले बदलावों को देखा जा सकता है और उन पर प्रतिक्रिया दी जा सकती है. उदाहरण के लिए, हर पेज में बदलाव होने पर, Analytics इवेंट भेजने के लिए, यह तरीका अपनाएं:
val pagerState = rememberPagerState(pageCount = { 10 }) LaunchedEffect(pagerState) { // Collect from the a snapshotFlow reading the currentPage snapshotFlow { pagerState.currentPage }.collect { page -> // Do something with each page change, for example: // viewModel.sendPageSelectedEvent(page) Log.d("Page change", "Page changed to $page") } } VerticalPager( state = pagerState, ) { page -> Text(text = "Page: $page") }
पेज इंडिकेटर जोड़ना
किसी पेज में इंडिकेटर जोड़ने के लिए, PagerState ऑब्जेक्ट का इस्तेमाल करके, यह जानकारी पाएं कि कई पेजों में से कौनसा पेज चुना गया है. इसके बाद, अपनी पसंद के मुताबिक इंडिकेटर बनाएं.
उदाहरण के लिए, सर्कल इंडिकेटर बनाने के लिए, pagerState.currentPage का इस्तेमाल करके, सर्कल की संख्या दोहराई जा सकती है. साथ ही, पेज चुने जाने पर सर्कल का रंग बदला जा सकता है:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, modifier = Modifier.fillMaxSize() ) { page -> // Our page content Text( text = "Page: $page", ) } Row( Modifier .wrapContentHeight() .fillMaxWidth() .align(Alignment.BottomCenter) .padding(bottom = 8.dp), horizontalArrangement = Arrangement.Center ) { repeat(pagerState.pageCount) { iteration -> val color = if (pagerState.currentPage == iteration) Color.DarkGray else Color.LightGray Box( modifier = Modifier .padding(2.dp) .clip(CircleShape) .background(color) .size(16.dp) ) } }
कॉन्टेंट पर आइटम स्क्रोल इफ़ेक्ट लागू करना
इसका एक सामान्य इस्तेमाल यह है कि पेजर आइटम पर इफ़ेक्ट लागू करने के लिए, स्क्रोल पोज़िशन का इस्तेमाल किया जाए. यह जानने के लिए कि कोई पेज, चुने गए पेज से कितनी दूरी पर है, आप
PagerState.currentPageOffsetFraction का इस्तेमाल कर सकते हैं. इसके बाद, चुने गए पेज से दूरी के आधार पर, अपने कॉन्टेंट पर ट्रांसफ़ॉर्मेशन इफ़ेक्ट लागू किए जा सकते हैं.
उदाहरण के लिए, आइटम के बीच की दूरी के आधार पर उनकी ओपैसिटी को अडजस्ट करने के लिए, सेंटर से उनकी दूरी के आधार पर आइटम की ओपैसिटी को अडजस्ट करने के लिए, पेजर में मौजूद किसी आइटम पर Modifier.graphicsLayer का इस्तेमाल करके, alpha में बदलाव करें:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager(state = pagerState) { page -> Card( Modifier .size(200.dp) .graphicsLayer { // Calculate the absolute offset for the current page from the // scroll position. We use the absolute value which allows us to mirror // any effects for both directions val pageOffset = ( (pagerState.currentPage - page) + pagerState .currentPageOffsetFraction ).absoluteValue // We animate the alpha, between 50% and 100% alpha = lerp( start = 0.5f, stop = 1f, fraction = 1f - pageOffset.coerceIn(0f, 1f) ) } ) { // Card content } }
पेज के कस्टम साइज़
डिफ़ॉल्ट रूप से, HorizontalPager पूरी चौड़ाई या VerticalPager पूरी ऊंचाई लेता है. आप pageSize वैरिएबल को
Fixed, Fill (डिफ़ॉल्ट), या कस्टम साइज़ के हिसाब से सेट कर सकते हैं.
उदाहरण के लिए, 100.dp की तय चौड़ाई वाला पेज सेट करने के लिए:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
व्यू पोर्ट के साइज़ के आधार पर पेजों का साइज़ तय करने के लिए, पेज के साइज़ के हिसाब से कस्टम सेटिंग का इस्तेमाल करें. कस्टम PageSize ऑब्जेक्ट बनाएं और आइटम के बीच की दूरी को ध्यान में रखते हुए, availableSpace को तीन से भाग दें:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
कॉन्टेंट पैडिंग
HorizontalPager और VerticalPager, दोनों में कॉन्टेंट पैडिंग बदलने की सुविधा होती है. इससे पेजों के ज़्यादा से ज़्यादा साइज़ और अलाइनमेंट पर असर पड़ता है.
उदाहरण के लिए, start पैडिंग सेट करने से, पेज आखिर की ओर अलाइन हो जाते हैं:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
start और end पैडिंग, दोनों को एक ही वैल्यू पर सेट करने से, आइटम दाएं-बाएं के बीच में अलाइन हो जाता है:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
end पैडिंग सेट करने से, पेज शुरुआत की ओर अलाइन हो जाते हैं:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
VerticalPager के लिए भी इसी तरह के इफ़ेक्ट पाने के लिए, top और bottom वैल्यू सेट की जा सकती हैं. यहां 32.dp वैल्यू का इस्तेमाल सिर्फ़ एक उदाहरण के तौर पर किया गया है. पैडिंग के हर डाइमेंशन के लिए कोई भी वैल्यू सेट की जा सकती है.
स्क्रोल करने के तरीके को पसंद के मुताबिक बनाना
HorizontalPager और VerticalPager के डिफ़ॉल्ट कंपोज़ेबल में यह तय किया जाता है कि पेजर के साथ स्क्रोलिंग जेस्चर कैसे काम करते हैं. हालांकि, pagerSnapDistance या flingBehavior जैसे डिफ़ॉल्ट को पसंद के मुताबिक बनाया जा सकता है और बदला जा सकता है.
स्नैप की दूरी
डिफ़ॉल्ट रूप से, HorizontalPager और VerticalPager में, फ़्लिंग जेस्चर से एक बार में स्क्रोल किए जा सकने वाले पेजों की ज़्यादा से ज़्यादा संख्या एक पेज पर सेट होती है. इसे बदलने
के लिए, pagerSnapDistance को flingBehavior पर सेट करें:
val pagerState = rememberPagerState(pageCount = { 10 }) val fling = PagerDefaults.flingBehavior( state = pagerState, pagerSnapDistance = PagerSnapDistance.atMost(10) ) Column(modifier = Modifier.fillMaxSize()) { HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(200.dp), beyondViewportPageCount = 10, flingBehavior = fling ) { PagerSampleItem(page = it) } }
अपने-आप आगे बढ़ने वाला पेजर बनाना
इस सेक्शन में, Compose में पेज इंडिकेटर के साथ अपने-आप आगे बढ़ने वाला पेजर बनाने का तरीका बताया गया है. आइटम का कलेक्शन, दाएं-बाएं अपने-आप स्क्रोल होता है. हालांकि, उपयोगकर्ता आइटम के बीच मैन्युअल तरीके से भी स्वाइप कर सकते हैं. अगर कोई उपयोगकर्ता पेजर से इंटरैक्ट करता है, तो यह अपने-आप आगे बढ़ने की प्रोसेस को रोक देता है.
सामान्य जानकारी
नीचे दिए गए स्निपेट मिलकर, विज़ुअल इंडिकेटर के साथ अपने-आप आगे बढ़ने वाले पेजर का सामान्य उदाहरण बनाते हैं. इसमें हर पेज अलग-अलग रंग में दिखता है:
@Composable fun AutoAdvancePager(pageItems: List<Color>, modifier: Modifier = Modifier) { Box(modifier = Modifier.fillMaxSize()) { val pagerState = rememberPagerState(pageCount = { pageItems.size }) val pagerIsDragged by pagerState.interactionSource.collectIsDraggedAsState() val pageInteractionSource = remember { MutableInteractionSource() } val pageIsPressed by pageInteractionSource.collectIsPressedAsState() // Stop auto-advancing when pager is dragged or one of the pages is pressed val autoAdvance = !pagerIsDragged && !pageIsPressed if (autoAdvance) { LaunchedEffect(pagerState, pageInteractionSource) { while (true) { delay(2000) val nextPage = (pagerState.currentPage + 1) % pageItems.size pagerState.animateScrollToPage(nextPage) } } } HorizontalPager( state = pagerState ) { page -> Text( text = "Page: $page", textAlign = TextAlign.Center, modifier = modifier .fillMaxSize() .background(pageItems[page]) .clickable( interactionSource = pageInteractionSource, indication = LocalIndication.current ) { // Handle page click } .wrapContentSize(align = Alignment.Center) ) } PagerIndicator(pageItems.size, pagerState.currentPage) } }
कोड के बारे में अहम बातें
AutoAdvancePagerफ़ंक्शन, दाएं-बाएं स्वाइप करके स्क्रोल करने वाला व्यू बनाता है, जो अपने-आप आगे बढ़ता है. यह इनपुट के तौर पर,Colorऑब्जेक्ट की सूची लेता है. इनका इस्तेमाल हर पेज के बैकग्राउंड कलर के तौर पर किया जाता है.pagerStateकोrememberPagerStateका इस्तेमाल करके बनाया जाता है. इसमें पेजर की स्थिति सेव होती है .pagerIsDraggedऔरpageIsPressed, उपयोगकर्ता के इंटरैक्शन को ट्रैक करते हैं.LaunchedEffect, पेजर को हर दो सेकंड में अपने-आप आगे बढ़ाता है. हालांकि, ऐसा तब तक होता है, जब तक उपयोगकर्ता पेजर को खींचता नहीं है या किसी पेज को दबाता नहीं है.HorizontalPager, पेजों की सूची दिखाता है. इनमें से हर पेज में, पेज नंबर दिखाने वालाTextकंपोज़ेबल होता है. मॉडिफ़ायर, पेज को भरता है,pageItemsसे बैकग्राउंड कलर सेट करता है, और पेज को क्लिक किया जा सकने वाला बनाता है.
@Composable fun PagerIndicator(pageCount: Int, currentPageIndex: Int, modifier: Modifier = Modifier) { Box(modifier = Modifier.fillMaxSize()) { Row( modifier = Modifier .wrapContentHeight() .fillMaxWidth() .align(Alignment.BottomCenter) .padding(bottom = 8.dp), horizontalArrangement = Arrangement.Center ) { repeat(pageCount) { iteration -> val color = if (currentPageIndex == iteration) Color.DarkGray else Color.LightGray Box( modifier = modifier .padding(2.dp) .clip(CircleShape) .background(color) .size(16.dp) ) } } } }
कोड के बारे में अहम बातें
Boxकंपोज़ेबल, रूट एलिमेंट के तौर पर काम करता है. इसमें पेज इंडिकेटर को दाएं-बाएं अलाइन करने के लिए,Rowहोता है.- कस्टम पेज इंडिकेटर, सर्कल की एक लाइन के तौर पर दिखता है. इसमें
CircleShapeपर क्लिप किया गया हरBox, एक पेज को दिखाता है. - मौजूदा पेज का सर्कल
DarkGrayरंग का होता है, जबकि अन्य सर्कलLightGrayरंग के होते हैं.currentPageIndexपैरामीटर से यह तय होता है कि कौनसा सर्कल गहरे ग्रे रंग में दिखेगा.
नतीजा
इस वीडियो में, पहले दिए गए स्निपेट से, अपने-आप आगे बढ़ने वाला सामान्य पेजर दिखाया गया है: