类似于 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), //用于滚动后手势的flingBehavior
- userScrollEnabled: 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
- )
- HorizontalPager(
- pageCount = 10,
- modifier = Modifier.size(100.dp)
- ) { page ->
- // 每一页的内容,比如显示个文本
- Text(
- text = "Page: $page",
- modifier = Modifier.fillMaxSize()
- )
- }
将 beyondBoundsPageCount 属性设为 >0 的整数,会在当前页面左右各加载相同数量的页面。
使用 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")
- }
通过 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.gray
- Box(modifier = Modifier
- .padding(2.dp)
- .clip(CircleShape)
- .background(color)
- .size(10.dp)
- )
- }
- }
- @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() }
- }
- }
- }
- }