برای ورق زدن محتوا به صورت افقی یا عمودی، میتوانید از Composable HorizontalPager و VerticalPager استفاده کنید. اینها عملکردهای مشابه ViewPager در سیستم view دارند. بهطور پیشفرض، 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 با تنبلی ترکیب شده و در صورت لزوم چیدمان می شوند. همانطور که کاربر در صفحات پیمایش می کند، composable صفحاتی را که دیگر مورد نیاز نیستند حذف می کند.
صفحات بیشتری را خارج از صفحه بارگیری کنید
به طور پیش فرض، پیجر فقط صفحات قابل مشاهده روی صفحه را بارگیری می کند. برای بارگیری بیشتر صفحات خارج از صفحه، beyondBoundsPageCount روی مقداری بالاتر از صفر تنظیم کنید.
به یک مورد در پیجر بروید
برای پیمایش به صفحه خاصی در پیجر، یک شی PagerState با استفاده از rememberPagerState() ایجاد کنید و آن را به عنوان پارامتر 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متفاوت است، زیرا اگر صفحه به اندازه کافی به موقعیت snap نزدیک شود،currentPageفوراً به روز می شود، اما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 }
برای اندازهگیری صفحات بر اساس اندازه نمایش، از یک محاسبه اندازه صفحه سفارشی استفاده کنید. یک شیء سفارشی PageSize ایجاد کنید و با در نظر گرفتن فاصله بین موارد، فضای availableSpace را بر سه تقسیم کنید:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
بالشتک محتوا
HorizontalPager و VerticalPager هر دو از تغییر padding پشتیبانی میکنند که به شما امکان میدهد حداکثر اندازه و تراز صفحات را تحت تأثیر قرار دهید.
به عنوان مثال، تنظیم صفحه 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 }
می توانید مقادیر top و bottom را برای دستیابی به جلوه های مشابه برای VerticalPager تنظیم کنید. مقدار 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لیستی از صفحات را نمایش می دهد که هر کدام دارای یک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) ) } } } }
نکات کلیدی در مورد کد
- یک
Boxcomposable به عنوان عنصر ریشه عمل می کند و حاوی یکRowبرای مرتب کردن نشانگرهای صفحه به صورت افقی است. - یک نشانگر صفحه سفارشی به صورت ردیفی از دایرهها نمایش داده میشود، که در آن هر
Boxبریده شده به یکCircleShapeنشاندهنده یک صفحه است. - دایره صفحه فعلی به رنگ
DarkGrayاست، در حالی که دایره های دیگرLightGrayهستند. پارامترcurrentPageIndexتعیین می کند که کدام دایره به رنگ خاکستری تیره نمایش داده می شود.
نتیجه
این ویدیو پیجر اصلی پیشروی خودکار را از قطعههای قبلی نشان میدهد: