Jetpack Compose HorizontalPager用Int.MAX_VALUE作页数触发IllegalArgumentException
问题:Jetpack Compose HorizontalPager无限滚动触发IllegalArgumentException错误
在Jetpack Compose中实现了基于HorizontalPager的无限滚动,初期运行正常,但近期滚动时触发如下错误:
java.lang.IllegalArgumentException: Cannot coerce value to an empty range: maximum -1564.0 is less than minimum 0.0
将pageCount从Int.MAX_VALUE替换为常量1000后问题消失,需要彻底解决该问题。
示例代码
val listSize = exploreList.size val pageCount = Int.MAX_VALUE val maxRounds = pageCount / listSize val initialPage = (maxRounds / 2) * listSize val pagerState = rememberPagerState(initialPage = initialPage, pageCount = { pageCount }) HorizontalPager( state = pagerState, modifier = Modifier.fillMaxWidth(), contentPadding = PaddingValues(horizontal = 54.dp), ) { val page = it % exploreList.size val id = exploreList.getOrNull(page)?.id ?: 0 val posterPath = exploreList.getOrNull(page)?.posterPath ExploreListItem( posterPath = posterPath, modifier = Modifier .fillMaxWidth() .aspectRatio(4F / 5F) .carousalTransition(it, pagerState), onClick = { navigateToMovieDetails(id) }, ) }
版本信息
- Compose BOM版本:
2023.10.01 - Kotlin版本:
1.9.21
原因分析
- 使用
Int.MAX_VALUE作为总页数会触发整数溢出:Pager内部在计算滚动偏移、页面位置时,超大数值的运算会超出Int或Float的取值范围,出现负数或非法的范围值,触发参数校验错误。 - 当
exploreList.size较大时,maxRounds = pageCount / listSize这类计算更容易溢出,后续initialPage的计算结果也会出现异常值,进一步导致Pager内部的范围校验失败。
解决方案
1. 使用合理的超大页数(推荐)
无需使用Int.MAX_VALUE,选择一个足够大但不会触发溢出的数值(如10000),既能满足无限滚动的用户体验,又能避免数值运算问题:
val listSize = exploreList.size.takeIf { it > 0 } ?: 1 // 避免列表为空时除以0 val pageCount = 10000 val maxRounds = pageCount / listSize val initialPage = (maxRounds / 2) * listSize val pagerState = rememberPagerState(initialPage = initialPage, pageCount = { pageCount })
2. 基于滚动回调的伪无限滚动(更优雅)
不依赖超大页数,而是在滚动到边界时主动切换到对应页面,实现无缝滚动,彻底避免数值溢出问题:
val listSize = exploreList.size val pagerState = rememberPagerState(pageCount = { listSize }) LaunchedEffect(pagerState.currentPage) { when (pagerState.currentPage) { // 滚动到第一页时,无缝跳转到最后一页 0 -> pagerState.scrollToPage(listSize - 1) // 滚动到最后一页时,无缝跳转到第一页 listSize - 1 -> pagerState.scrollToPage(0) } } HorizontalPager( state = pagerState, modifier = Modifier.fillMaxWidth(), contentPadding = PaddingValues(horizontal = 54.dp), ) { page -> val item = exploreList[page] ExploreListItem( posterPath = item.posterPath, modifier = Modifier .fillMaxWidth() .aspectRatio(4F / 5F) .carousalTransition(page, pagerState), onClick = { navigateToMovieDetails(item.id) }, ) }
这种方式逻辑更清晰,也不会有数值溢出的风险,是实现无限滚动的最优方案。
内容的提问来源于stack exchange,提问作者Mubashir P A
相关产品推荐
相关产品推荐

