You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:27:41