Jetpack Compose Banner即拿即用

Jetpack Compose目前没有官方的Banner控件,所以只能自己写,搜了些资料才完成,非常感谢之前分享过这些内容的大佬们。

效果图

accompanist组库

accompanist

旨在为Jetpack Compose提供补充功能的组库,里面有非常多很好用的实验性功能,之前用过的加载网络图片的rememberImagePainter就是其中之一,而做Banner的话需要用到的是其中的Pager库。

//导入依赖 
implementation "com.google.accompanist:accompanist-pager:$accompanist_pager"

这里我用的是0.16.1,因为其他库也是这个版本,目前最新是0.18.0

关键代码

1、rememberPagerState

用于记录分页状态的变量,一共有5个参数,我们用到了4个,还有一个是initialPageOffset,可以设置偏移量

val pagerState = rememberPagerState(
    //总页数
    pageCount = list.size,
    //预加载的个数
    initialOffscreenLimit = 1,
    //是否无限循环
    infiniteLoop = true,
    //初始页面
    initialPage = 0
)
2、HorizontalPager

用于创建一个可以横向滑动的分页布局,把上面的rememberPagerState传进去,其他也没啥

HorizontalPager(
    state = pagerState,
    modifier = Modifier
        .fillMaxSize(),
) {
    page ->
    Image(
        painter = rememberImagePainter(list[page].imageUrl),
        modifier = Modifier.fillMaxSize(),
        contentScale = ContentScale.Crop,
        contentDescription = null
    )
}
3、让HorizontalPager自己动起来

这里有两个方法可以让HorizontalPager动起来,一个是animateScrollToPage***,另一个是scrollToPage*,从名字上都可以看出来带animate的是有动画效果的方法,也正是我想要的东西。

//自动滚动
LaunchedEffect(pagerState.currentPage) {
   
    if (pagerState.pageCount > 0) {
   
        delay(timeMillis)
        pagerState.animateScrollToPage((pagerState.currentPage + 1) % pagerState.pageCount)
    }
}

在控件里添加这行代码就可以让控件自动起来了

但这是一段看起来没问题的代码

假设页面总数pagerState.pageCount为2,当((pagerState.currentPage + 1) % pagerState.pageCount) == 0时跳转到第1个页面,但最后的效果是这样的

轮播图往左滑了,而且还出现了轮播图中间页面的画面,页面有点闪烁的感觉。

修改后
//自动滚动
LaunchedEffect(pagerState.currentPage) {
   
    if (pagerState.pageCount > 0) {
   
        delay(timeMillis)
        //这里直接+1就可以循环,前提是pagerState的infiniteLoop == true
        pagerState.animateScrollToPage(pagerState.currentPage + 1)
    }
}

只修改了animateScrollToPage参数的值,看到这里可能有人会问:pagerState.currentPage + 1不会报错吗?

确实不会!

因为当rememberPagerState中的infiniteLoop(无限循环)参数设置为true时最大页码其实为Int.MAX_VALUE,而currentPage只是当前页面的索引,并不是真实的页码。

也就是说,当Banner有4个页面,这里传个5的时候,并不会报错,而且animateScrollToPage会自动将这个"5"转换为页面索引,以保证下次使用currentPage不会出错。(菜鸟,我!啊吧啊吧看了好一阵子源码没看到这个是哪里转的)

不过有些地方值得注意:

调用pagerState.animateScrollToPage(target)的时候

  • 当target > pageCount 或 target > currentPage的时候,控件向右滑动
  • 当target < pageCount 且 target < currentPage的时候,控件向左滑动
  • 另外如果currentPage和target当两者相差页面大于4的时候只会在动画中显示(currentPage、currentPage + 1、target - 1、target)四个页面

以此类推,如果改为-1的话就是不断往左自动滑动啦

pagerState.animateScrollToPage(pagerState.currentPage - 1)

Banner中定义了几个参数,indicatorAlignment可以设置指示点的位置,默认为底部居中


/** 
 * 轮播图
 * [timeMillis] 停留时间
 * [loadImage] 加载中显示的布局
 * [indicatorAlignment] 指示点的的位置,默认是轮播图下方的中间,带一点padding
 * [onClick] 轮播图点击事件
 */
@ExperimentalCoilApi
@ExperimentalPagerApi
@Composable
fun Banner(
    list: List<BannerData>?,
    timeMillis: Long = 3000,
    @DrawableRes loadImage: Int = R.mipmap.ic_web,
    indicatorAlignment: Alignment
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值