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

如何在Jetpack Compose的HorizontalPager中无中间页跳转并保留动画

解决HorizontalPager跨页跳转显示中间页面的问题

默认调用animateScrollToPage跨页跳转时(比如从第0页到第2页),Pager会逐页滚动,导致中间页面短暂显示。要实现直接跳转且保留切换动画,可采用以下方案:

核心思路

通过直接计算并滚动目标页与当前页的像素偏移量,替代按页面数量的逐页滚动,让Pager直接滑到目标位置,跳过中间页面的视觉展示。

具体实现步骤

  1. 获取Pager宽度:通过Modifier.onSizeChanged监听HorizontalPager的宽度,用于计算滚动偏移量。
  2. 替换跳转逻辑:将原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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:07:03