कॉन्टेंट को दाएं से बाएं या ऊपर से नीचे की ओर फ़्लिप करने के लिए, 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 को शून्य से ज़्यादा पर सेट करें.
पेजर में किसी आइटम पर स्क्रोल करना
पेजर में किसी पेज पर स्क्रोल करने के लिए, rememberPagerState() का इस्तेमाल करके PagerState ऑब्जेक्ट बनाएं. इसके बाद, इसे पेजर में 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, फ़्लिंग जेस्चर से एक बार में स्क्रोल किए जा सकने वाले पेजों की ज़्यादा से ज़्यादा संख्या को एक पेज पर सेट करते हैं. इसे बदलने के लिए, flingBehavior पर pagerSnapDistance सेट करें:
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होता है, ताकि पेज इंडिकेटर को हॉरिज़ॉन्टल तरीके से व्यवस्थित किया जा सके.- कस्टम पेज इंडिकेटर को सर्कल की एक लाइन के तौर पर दिखाया जाता है. इसमें हर
Box,CircleShapeमें क्लिप किया गया एक पेज होता है. - मौजूदा पेज के सर्कल को
DarkGrayके तौर पर रंगा गया है, जबकि अन्य सर्कलLightGrayहैं.currentPageIndexपैरामीटर से यह तय होता है कि कौनसी सर्कल गहरे स्लेटी रंग में रेंडर होगी.
नतीजा
इस वीडियो में, पिछले स्निपेट से मिले बुनियादी ऑटो-ऐडवांसिंग पेजर को दिखाया गया है: