如何在Jetpack Compose的HorizontalPager中无中间页跳转并保留动画
解决HorizontalPager跨页跳转显示中间页面的问题
默认调用animateScrollToPage跨页跳转时(比如从第0页到第2页),Pager会逐页滚动,导致中间页面短暂显示。要实现直接跳转且保留切换动画,可采用以下方案:
核心思路
通过直接计算并滚动目标页与当前页的像素偏移量,替代按页面数量的逐页滚动,让Pager直接滑到目标位置,跳过中间页面的视觉展示。
具体实现步骤
- 获取Pager宽度:通过
Modifier.onSizeChanged监听HorizontalPager的宽度,用于计算滚动偏移量。 - 替换跳转逻辑:将原
animateScrollToPage调用改为计算偏移量后调用animateScrollBy。
修改后的完整代码
@Composable fun MyAppNavigation( modifier: Modifier, authViewModel: AuthViewModel ) { val pages = registerInfoList.size val pagerState = rememberPagerState(pageCount = { pages }) val scope = rememberCoroutineScope() val shouldRequestFocus = remember { mutableStateOf(true) } // 存储Pager的宽度,用于计算滚动偏移 val pagerWidth = remember { mutableStateOf(0f) } Column( modifier = modifier.fillMaxSize() ) { HorizontalPager( state = pagerState, userScrollEnabled = false, // 监听Pager尺寸变化,获取宽度 modifier = Modifier.onSizeChanged { size -> pagerWidth.value = size.width.toFloat() } ) { page -> when (page) { 0 -> StartPage( modifier = modifier, toSignUp = { scope.launch { val targetPage = 2 // 计算需要滚动的总像素距离 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, toLogin = { scope.launch { val targetPage = 1 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, authViewModel = authViewModel ) 1 -> LoginPage( modifier = modifier, toHome = { scope.launch { val targetPage = 3 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, toSignUp = { scope.launch { val targetPage = 2 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, toStart = { scope.launch { val targetPage = 0 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, authViewModel = authViewModel ) 2 -> SignupPage( modifier = modifier, toStart = { scope.launch { val targetPage = 0 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, toHome = { scope.launch { val targetPage = 3 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, authViewModel = authViewModel ) 3 -> HomePage( modifier = modifier, toStart = { scope.launch { val targetPage = 0 val scrollDistance = (targetPage - pagerState.currentPage) * pagerWidth.value pagerState.animateScrollBy(scrollDistance) } }, authViewModel = authViewModel ) } } } }
原理说明
animateScrollBy直接操作像素级的滚动偏移,而非按页面数量逐步滚动。从第0页到第2页时,Pager会一次性滚动两个页面宽度的距离,视觉上直接滑到目标页,中间页面不会被展示。
内容的提问来源于stack exchange,提问作者Fatima Jamal
相关产品推荐
相关产品推荐

