当前位置: 首页 > news >正文

广西做网站建设的公司福建做网站

广西做网站建设的公司,福建做网站,个人主页图片,做网站多久能学会Jetpack Compose:使用PagerIndicator和Infinity实现滚动的HorizontalPager 可能你已经知道,Jetpack Compose 默认不包含内置的ViewPager组件。然而,我们可以通过在 build.gradle 文件中添加 accompanist 库依赖,将 ViewPager 功能…

Jetpack Compose:使用PagerIndicator和Infinity实现滚动的HorizontalPager

Android | Kotlin | Jetpack Compose | ViewPager | PagerIndicator
可能你已经知道,Jetpack Compose 默认不包含内置的ViewPager组件。然而,我们可以通过在 build.gradle 文件中添加 accompanist 库依赖,将 ViewPager 功能集成到我们的项目中。

implementation "com.google.accompanist:accompanist-pager:0.28.0"

为了将指示器纳入其中,我们还将利用accompanist库。

implementation "com.google.accompanist:accompanist-pager-indicators:0.28.0"

注意:对于此项目,我们使用的是Compose版本1.3.1和Kotlin版本1.8.10。
在这里插入图片描述

让我们从创建一个HorizontalPager 开始

accompanist库的存在,创建HorizontalPager是一项简单的任务。

HorizontalPager(count = pageCount,state = pagerState,modifier = modifier
) {// page content
}
  • Count:页面数
    我们将计数设置为非常大的数,如Int.MAX_VALUE,这样我们就可以实现无限滚动行为。
// Used Int.MAX_VALUE for infinity scroll
val pageCount = Int.MAX_VALUE
  • State:用于控制或观察分页器状态的状态对象。
    对于状态创建,我们只需要 initialPage 值。为了实现双向无限滚动,我们应该从给定页面计数的中间开始。因此,initialPage 可以设置如下示例:
val middlePage = pageCount / 2
val pagerState = rememberPagerState(initialPage = middlePage)

尽管一开始所有东西似乎都是正确的,但我们很快就会遇到一个涉及最初显示页面的问题。

技巧

为了实现ViewPager的无限行为,我们通过设置计数为一个非常大的数字来实现了一种解决方案。但是,我们实际的物品列表(奖杯)要小得多。为了确保ViewPager显示我们真正列表中的正确页面而不创建重复页面,我们需要适当地处理页面编号。

为了解决这个挑战,我们将提供的页面编号除以奖杯列表的大小。这个除法允许我们在我们的真实列表中获取正确的页面索引。通过执行这个计算,我们确保ViewPager只显示列表中的实际物品,防止任何重复。

通过利用这种方法,我们可以在ViewPager中轻松导航通过奖杯列表,同时保持其无限行为。

看下面的例子:

val realSize = trophies.sizeHorizontalPager(count = pageCount,state = pagerState,modifier = modifier
) { page -> val realPage = page % realSize// max value is trophies.sizeTrophyWidget(realPage, trophy = trophies[realPage])
}

你懂了吗?不懂?(那我们就来算一下吧!)
page count

看起来我们的数学运算正常运行!

如果您仔细观察,就会发现初始页面不是奖杯列表中的第一个。实际上,初始状态取决于奖杯列表的大小。为了解决这个差异并确保正确的初始状态,有必要计算并传递一个参数到ViewPager状态。

val realSize = trophies.sizeval middlePage = pageCount / 2
// Init the PagerState with a very large number and make it always start from the first item of the real list
val pagerState = rememberPagerState(initialPage = middlePage - (middlePage % realSize))

通过将middlePage减去middlePage与奖杯数量取余的结果,确保ViewPager将从奖杯列表的开头开始。

页面指示器

添加指示器也很简单,我们只需要添加HorizontalPagerIndicator并将pagerState作为参数传递即可。

Android | HorizontalPager | Indicator
然而,这里存在一个问题!如果您尝试在不指定列表(奖杯)的实际大小的情况下使用pagerState,则应用程序将会空白页。那是因为HorizontalPagerIndicator的默认pageCount设置为PagerState.pageCount的值,而在我们的情况下,这是一个非常大的数。

幸运的是,我们可以通过将pageCount作为参数添加到HorizontalPagerIndicator中来指定pageCount

看一个例子:

HorizontalPagerIndicator(pagerState = pagerState,pageCount = realSize,pageIndexMapping = { it % realSize },activeColor = Color.White,modifier = modifier.align(Alignment.BottomCenter).padding(bottom = 12.dp)
)

我们还必须描述如何通过将页面传递给pageIndexMapping函数来获取活动指示器的位置。这可以通过将pagerState.currentPage除以奖杯列表的大小来实现。

如上例所示,您可以实现以下代码段:

pageIndexMapping = { currentPage % realSize }

要获取活动指示器的位置,您可以使用pageIndexMapping函数,并使用pagerState.currentPage和奖杯列表的大小执行模运算。

自动滚动

如果您还需要您的页面自动滚动,可以使用以下代码片段:

// Start auto-scroll effect
LaunchedEffect(isDraggedState) {// convert compose state into flowsnapshotFlow { isDraggedState.value }.collectLatest { isDragged ->// if not isDragged start slide animationif (!isDragged) {// infinity loopwhile (true) {// duration before each scroll animationdelay(5_000L)runCatching {pagerState.animateScrollToPage(pagerState.currentPage.inc() % pagerState.pageCount)}}}}
}

完整代码如下:

private const val SCROLL_ANIMATION_DURATION = 5_000L@OptIn(ExperimentalPagerApi::class)
@Composable
fun InfinityHorizontalPager(modifier: Modifier = Modifier) {Column(verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {Box(modifier = modifier.fillMaxWidth().height(400.dp)) {// Used Int.MAX_VALUE for infinity scrollval pageCount = Int.MAX_VALUE// The actual view pager size (for the HorizontalPagerIndicator)val realSize = trophies.size// Start from the middle in order to the infinity scroll for both sidesval middlePage = pageCount / 2// Init the PagerState with a very large number and make it always start from the first item of the real listval pagerState = rememberPagerState(initialPage = middlePage - (middlePage % realSize))val isDraggedState = pagerState.interactionSource.collectIsDraggedAsState()HorizontalPager(count = pageCount,state = pagerState,modifier = modifier.fillMaxWidth().fillMaxHeight().background(MaterialTheme.colors.background),) {val page = it % realSize// max value is trophies.sizeTrophyWidget(page, trophy = trophies[page])}Surface(modifier = Modifier.padding(bottom = 8.dp).align(Alignment.BottomCenter),shape = CircleShape,color = Color.Black.copy(alpha = 0.5f)) {HorizontalPagerIndicator(pagerState = pagerState,pageCount = realSize,pageIndexMapping = { it % realSize },activeColor = Color.White,modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp))}// Start auto-scroll effectLaunchedEffect(isDraggedState) {// convert compose state into flowsnapshotFlow { isDraggedState.value }.collectLatest { isDragged ->// if not isDragged start slide animationif (!isDragged) {// infinity loopwhile (true) {// duration before each scroll animationdelay(SCROLL_ANIMATION_DURATION)runCatching {pagerState.animateScrollToPage(pagerState.currentPage.inc() % pagerState.pageCount)}}}}}}}
}@Composable
fun TrophyWidget(page: Int,trophy: TrophyCard,modifier: Modifier = Modifier
) {Box(modifier = modifier.padding(horizontal = 16.dp).fillMaxWidth().fillMaxHeight().background(Color.Black).clip(shape = RoundedCornerShape(size = 12.dp)),) {AsyncImage(model = ImageRequest.Builder(LocalContext.current).data(trophy.image).crossfade(true).build(),modifier = modifier.fillMaxWidth().fillMaxHeight().clip(shape = RoundedCornerShape(size = 12.dp)),contentDescription = null,contentScale = ContentScale.FillBounds)Column(modifier = Modifier.fillMaxWidth().background(color = Color.Black.copy(alpha = 0.5f)).padding(10.dp).align(Alignment.BottomStart)) {Text(text = trophy.location,color = Color.White,style = Typography.h6,textAlign = TextAlign.Center)Text(text = trophy.year,color = Color.White,style = Typography.h4,textAlign = TextAlign.Center)}Text(text = "$page",style = Typography.body1,color = Color.Black,textAlign = TextAlign.Center,modifier = Modifier.padding(10.dp).clip(shape = RoundedCornerShape(size = 4.dp)).background(Color.White).padding(10.dp).align(Alignment.BottomEnd))}
}@Preview(showBackground = true, showSystemUi = true)
@Composable
fun DefaultPreview() {InfinityPagerTheme {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colors.background) {InfinityHorizontalPager()}}
}

在这里插入图片描述

http://www.yayakq.cn/news/368168/

相关文章:

  • 自己做网站代码手机分销网站建设
  • 建筑工程类网站巴中市住房和城乡建设局网站
  • 文登建设局网站本周新闻热点
  • 网站建设学习网公司有哪些nodejs做网站能保护源代码吗
  • 宁夏网站推广通过信息系统融合和创新形成企业解决方案
  • wordpress网站响应速度插件哈尔滨模版建站公司推荐
  • 用jsp做网站的技术路线网页升级访问升级
  • 课题网站建设验收总结报告wordpress 修改源码
  • 单页应用网站网页设计基础知识试题
  • 领优惠券的网站怎么做上线了相同网站
  • delphi 实现网站开发陕西省两学一做网站
  • 网站建设方案策划书前言青岛百度公司总部
  • 网站页面链接结构深圳设计周展会2024时间
  • 网站建设困难简洁的网站地图模板
  • 东城网站制作公司免费logo在线生成器
  • 网站空间管理站贵阳网站开发人员工资
  • 自助搭建网站襄樊北京网站建设
  • 设计本官方网站电脑版青岛专业做网站的
  • 怎么区别网站开发语言徐州铜山区建设局网站
  • 效果好的徐州网站建设临西做网站哪里便宜
  • 做ppt兼职的网站福利wordpress
  • 宁德城乡建设部网站首页微信直接下载安装
  • 做名片网站成都消防设计公司
  • 阿里云服务器发布网站一个网站怎么做软件下载
  • 那个餐饮网站网页设计教程孟宪宁
  • 天津网站建设业务wordpress网站更换域名
  • 大型网站开发工具销售易crm官网
  • 手机建站平台可上传自己视频网站建站网站看看
  • 自己创建一个网站需要多少钱北京建设协会网站
  • 销项税和进项导入是在国税网站做吗html代码 wordpress