برای ورق زدن محتوا به صورت افقی یا عمودی، میتوانید از Composableهای HorizontalPager و VerticalPager استفاده کنید. این Composableها عملکردهای مشابهی با ViewPager در سیستم نمایش دارند. به طور پیشفرض، HorizontalPager تمام عرض صفحه و VerticalPager تمام ارتفاع را اشغال میکند. همچنین، Pagerها فقط یک صفحه را در یک زمان جابجا میکنند. همه این مقادیر پیشفرض قابل تنظیم هستند.
پیجر افقی
 برای ایجاد یک پیجر که به صورت افقی به چپ و راست اسکرول میکند، از 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 
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
آفرینش تنبل
 صفحات در هر دو HorizontalPager و VerticalPager به صورت تنبل (lazyly) ترکیب و چیدمان میشوند و در صورت نیاز، طرحبندی میشوند. با اسکرول کردن کاربر در صفحات، صفحهساز صفحاتی را که دیگر نیازی به آنها نیست، حذف میکند.
بارگذاری صفحات بیشتر خارج از صفحه
 به طور پیشفرض، پیجر فقط صفحات قابل مشاهده روی صفحه را بارگذاری میکند. برای بارگذاری صفحات بیشتر خارج از صفحه، beyondBoundsPageCount روی مقداری بالاتر از صفر تنظیم کنید.
به یک مورد در صفحهنگار بروید
 برای اسکرول کردن به یک صفحه خاص در صفحهبند، با استفاده از rememberPagerState() یک شیء PagerState ایجاد کنید و آن را به عنوان پارامتر state به صفحهبند منتقل کنید. میتوانید PagerState#scrollToPage() در این حالت، درون یک CoroutineScope فراخوانی کنید: 
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: نزدیکترین صفحه به موقعیت snap. به طور پیشفرض، موقعیت snap در ابتدای طرحبندی است. -  
settledPage: شماره صفحه زمانی که هیچ انیمیشن یا پیمایشی در حال اجرا نیست. این با ویژگیcurrentPageمتفاوت است، زیراcurrentPageبلافاصله اگر صفحه به اندازه کافی به موقعیت snap نزدیک باشد، بهروزرسانی میشود، اماsettledPageتا زمانی که اجرای تمام انیمیشنها تمام شود، ثابت میماند. -  
targetPage: موقعیت توقف پیشنهادی برای حرکت اسکرول. 
 شما میتوانید از تابع snapshotFlow برای مشاهده تغییرات این متغیرها و واکنش به آنها استفاده کنید. برای مثال، برای ارسال یک رویداد تحلیلی در هر تغییر صفحه، میتوانید موارد زیر را انجام دهید: 
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 استفاده کنید. سپس میتوانید جلوههای تبدیل را بر اساس فاصله از صفحه انتخاب شده به محتوای خود اعمال کنید. 
 برای مثال، برای تنظیم میزان شفافیت آیتمها بر اساس فاصله آنها از مرکز، alpha با استفاده از Modifier.graphicsLayer روی یک آیتم درون صفحهساز تغییر دهید: 
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 }
 برای اندازهبندی صفحات بر اساس اندازهی viewport، از یک محاسبهی اندازهی صفحهی سفارشی استفاده کنید. یک شیء PageSize سفارشی ایجاد کنید و availableSpace با در نظر گرفتن فاصلهی بین آیتمها، بر سه تقسیم کنید: 
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
پر کردن محتوا
 HorizontalPager و VerticalPager هر دو از تغییر فاصله بین محتوا (content padding) پشتیبانی میکنند که به شما امکان میدهد حداکثر اندازه و ترازبندی صفحات را تنظیم کنید.
 برای مثال، تنظیم فاصله start ، صفحات را به سمت انتها تراز میکند: 

val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
 تنظیم مقدار یکسان برای padding start و end ، آیتم را به صورت افقی در مرکز قرار میدهد: 

val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
 تنظیم padding end ، صفحات را به سمت شروع تراز میکند: 

val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
 شما میتوانید مقادیر top و bottom را برای دستیابی به جلوههای مشابه برای VerticalPager تنظیم کنید. مقدار 32.dp در اینجا فقط به عنوان مثال استفاده شده است؛ میتوانید هر یک از ابعاد padding را روی هر مقداری تنظیم کنید.
سفارشیسازی رفتار اسکرول
 کامپوننتهای پیشفرض HorizontalPager و VerticalPager نحوهی عملکرد حرکات اسکرول با پیجر را مشخص میکنند. با این حال، میتوانید پیشفرضها مانند pagerSnapDistance یا flingBehavior را سفارشیسازی و تغییر دهید.
فاصله اسنپ
 به طور پیشفرض، HorizontalPager و VerticalPager حداکثر تعداد صفحاتی را که یک حرکت fling میتواند همزمان به یک صفحه پیمایش کند، تنظیم میکنند. برای تغییر این، 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ایجاد میشود که وضعیت pager را در خود نگه میدارد. -  
pagerIsDraggedوpageIsPressedتعامل کاربر را ردیابی میکنند. -  
LaunchedEffectبه طور خودکار هر دو ثانیه صفحه را به جلو میبرد، مگر اینکه کاربر صفحه را بکشد یا یکی از صفحات را فشار دهد. -  
HorizontalPagerفهرستی از صفحات را نمایش میدهد که هر کدام دارای یکTextcomposable هستند که شماره صفحه را نمایش میدهد. این اصلاحکننده صفحه را پر میکند، رنگ پسزمینه را از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تعیین میکند که کدام دایره به رنگ خاکستری تیره نمایش داده شود. 
نتیجه
این ویدیو، صفحهگردان خودکار اولیه را از قطعه کدهای قبلی نمایش میدهد: