要以左右或上下方式翻阅内容,您可以分别使用 HorizontalPager
和 VerticalPager
可组合项。这些可组合项的功能与视图系统中的 ViewPager
类似。默认情况下,HorizontalPager
占据屏幕的全部宽度,VerticalPager
占据全部高度,并且翻页器每次只翻动一页。这些默认值都是可配置的。
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
中的页面在需要时会 延迟组合 和布局。当用户滚动浏览页面时,可组合项会移除不再需要的任何页面。
加载屏幕外的更多页面
默认情况下,翻页器仅加载屏幕上的可见页面。要加载屏幕外的更多页面,请将 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
函数观察这些变量的变化并做出反应。例如,要针对每次页面更改发送分析事件,您可以执行以下操作
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
除以 3,同时考虑项目之间的间距
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 }
您可以设置 top
和 bottom
值以对 VerticalPager
产生类似的效果。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), beyondBoundsPageCount = 10, flingBehavior = fling ) { PagerSampleItem(page = it) } }
为您推荐
- 注意:当 JavaScript 关闭时,会显示链接文本
- Compose 中的 ConstraintLayout
- 图形修饰符
- 将
CoordinatorLayout
迁移到 Compose