LaunchedEffect中HorizontalPager自动滚动isPaused状态异常问题
问题解决:HorizontalPager自动滚动状态异常修复
问题根源
你遇到的isPaused状态始终为false、长按后LaunchedEffect触发两次且状态异常的问题,核心原因是HorizontalPager的页面content块中强制设置了isPaused = false:
in items.indices -> { isPaused = false // 这里每次页面渲染都会重置状态 content(items[pageIndex]) }
每当页面重组(包括自动滚动、手动滑动、长按操作后),这段代码都会把isPaused强制改回false,导致你长按设置的true状态根本无法保留,同时触发LaunchedEffect多次重启。
修复方案
1. 移除页面content中的状态重置
首先删掉content块里的isPaused = false,避免状态被强制覆盖。
2. 监听手动滑动恢复自动滚动
添加对pagerState.isScrollInProgress的监听,当用户手动滑动结束后,自动恢复滚动状态:
LaunchedEffect(pagerState.isScrollInProgress) { if (!pagerState.isScrollInProgress) { isPaused = false } }
3. 优化自动滚动逻辑
调整LaunchedEffect的逻辑,确保状态变化时协程能正确启停:
LaunchedEffect(isPaused) { println("LaunchedEffect $isPaused") if (isPaused) return@LaunchedEffect while (true) { delay(3000) if (isPaused) break val nextPage = (pagerState.currentPage + 1) % items.count() pagerState.animateScrollToPage(nextPage) } }
4. 修正点击跳转的边界判断
原代码中点击跳转的边界条件会导致最后一页越界,修改为:
onClick = { if (pagerState.currentPage < items.count() - 1) { isPaused = false println("onClick $isPaused") coroutineScope.launch { val nextPage = pagerState.currentPage + 1 pagerState.animateScrollToPage(nextPage) } } }
完整修复代码
val coroutineScope = rememberCoroutineScope() var isPaused by remember { mutableStateOf(false) } val pagerState = rememberPagerState() // 监听手动滑动结束,恢复自动滚动 LaunchedEffect(pagerState.isScrollInProgress) { if (!pagerState.isScrollInProgress) { isPaused = false } } // 自动滚动逻辑 LaunchedEffect(isPaused) { println("LaunchedEffect $isPaused") if (isPaused) return@LaunchedEffect while (true) { delay(3000) if (isPaused) break val nextPage = (pagerState.currentPage + 1) % items.count() pagerState.animateScrollToPage(nextPage) } } // HorizontalPager实现 HorizontalPager( state = pagerState, pageSpacing = 16.dp, modifier = modifier .fillMaxSize() .combinedClickable( onLongClick = { isPaused = true println("onLongClick $isPaused") }, onClick = { if (pagerState.currentPage < items.count() - 1) { isPaused = false println("onClick $isPaused") coroutineScope.launch { val nextPage = pagerState.currentPage + 1 pagerState.animateScrollToPage(nextPage) } } } ) ) { pageIndex -> when (pageIndex) { in items.indices -> { content(items[pageIndex]) } else -> { lastItemContent?.invoke() } } }
修复后效果
- 长按页面:
isPaused设为true,自动滚动暂停,日志输出onLongClick true和LaunchedEffect true - 点击页面:立即跳转到下一页,自动滚动恢复,日志输出
onClick false和LaunchedEffect false - 手动滑动页面:滑动结束后自动恢复滚动,
isPaused重置为false
内容的提问来源于stack exchange,提问作者ant2009
相关产品推荐
相关产品推荐

