Compose 可组合项 - 分页器 HorizontalPager、VerticalPager

一、概念

类似于 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
)

二、使用

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.gray
        Box(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() }
           }
       }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值