一、概念
类似于 ViewPager,1.4 版本之前需要借助 accompanis 库,底层基于 LazyColumn、LazyRow 实现,在使用上也基本相同。默认情况下 HorizontalPager 占据屏幕的整个宽度,VerticalPager 会占据整个高度。
fun HorizontalPager(pageCount: Int, //页面数量modifier: Modifier = Modifier,state: PagerState = rememberPagerState(), //控制监听页面状态的对象contentPadding: PaddingValues = PaddingValues(0.dp), //内容内边距pageSize: PageSize = PageSize.Fill, //页面填充模式(填充满Fill,自适应Fixed)beyondBoundsPageCount: Int = 0, //当前页面前后预加载的页面数量pageSpacing: Dp = 0.dp, //两个页面之间的间隙verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,flingBehavior: SnapFlingBehavior = PagerDefaults.flingBehavior(state = state), //用于滚动后手势的flingBehavioruserScrollEnabled: Boolean = true, //是否允许通过用户手势或辅助功能进行滚动(即使禁用PagerState.scroll,您仍然可以使用它以编程方式滚动)reverseLayout: Boolean = false, //反转页面顺序key: ((index: Int) -> Any)? = null, //表示项目的稳定且唯一的密钥。当您指定键时,滚动位置将根据键保持,这意味着如果您在当前可见项目之前添加/删除项目,则具有给定键的项目将保留为第一个可见项目。pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(Orientation.Horizontal), //一个嵌套的ScrollConnection,用于指示此Pager如何使用嵌套列表。默认行为将使Pager消耗所有嵌套的delta。pageContent: @Composable (page: Int) -> Unit
)
二、使用
2.1 简单使用
HorizontalPager(pageCount = 10,modifier = Modifier.size(100.dp)
) { page ->// 每一页的内容,比如显示个文本Text(text = "Page: $page",modifier = Modifier.fillMaxSize())
}
2.2 离屏加载更多页面
将 beyondBoundsPageCount 属性设为 >0 的整数,会在当前页面左右各加载相同数量的页面。
2.3 控制页面滚动
使用 rememberPagerState() 创建一个 PagerState 对象,并将其作为 state 参数传递给分页器。在 CoroutineScope 中对此状态调用 PagerState.scrollToPage(),带动画跳转使用 PagerState.animateScrollToPage()。
val pagerState = rememberPagerState( 10 ) //10是页面数量HorizontalPager(state = pagerState,modifier = Modifier.size(100.dp)
) { page ->Text(text = "Page: $page",modifier = Modifier.fillMaxSize())
}val coroutineScope = rememberCoroutineScope()
Button(modifier = Modifier.align(Alignment.BottomCenter),onClick = {coroutineScope.launch {pagerState.scrollToPage(5)
// pagerState.animateScrollToPage(5) //带动画跳转}}
) {Text("跳到页面5")
}
2.4 添加页面指示器
2.4.1 小圆点
通过 pagerState.pageCount 获取页面数量,并绘制自定义指示器。使用 pagerState.currentPage 获取当前显示页面的索引,改变对应指示器的颜色。
Row(modifier = Modifier.align(Alignment.BottomCenter).fillMaxWidth().padding(bottom = 2.dp),horizontalArrangement = Arrangement.Center
) {repeat(pagerState.pageCount) { index ->val color = if (pagerState.currentPage == index) Colors.black else Colors.grayBox(modifier = Modifier.padding(2.dp).clip(CircleShape).background(color).size(10.dp))}
}
2.4.2 Tab栏
@Composable
fun Demo() {val tabList = listOf("最新","广场","问答","项目")val pagerState = rememberPagerState { tabList.size }val coroutineScope = rememberCoroutineScope()Column(modifier = Modifier.fillMaxSize()) {TabRow(modifier = Modifier.padding(vertical = 10.dp).fillMaxWidth().height(20.dp),selectedTabIndex = pagerState.currentPage,containerColor = AppColors.transparent,indicator = {},divider = {}) {tabList.forEachIndexed { index, title ->Tab(text = { Text(text = title,fontSize = if (pagerState.currentPage == index) 15.sp else 15.sp,fontWeight = if (pagerState.currentPage == index) FontWeight.ExtraBold else FontWeight.Bold) },selected = pagerState.currentPage == index,selectedContentColor = AppTheme.colors.textPrimary,unselectedContentColor = AppTheme.colors.textSecondary,onClick = { coroutineScope.launch { pagerState.scrollToPage(index) } })}}HorizontalPager(state = pagerState,beyondBoundsPageCount = 1,pageSpacing = Dimension.contentMargin) { index ->when (index) {0 -> { NewestPage() }1 -> { SquarePage() }2 -> { QaPage() }3 -> { ProjectPage() }}}}
}