androiduser-interfaceandroid-jetpack-composehorizontal-pager

How to navigate to specific page without intermediate pages?


I have the pages of my App in a horizontalPager for example if i navigate to page 2, and i'm currently at page 0, page 1 does show, how i prevent it from showing.

I want only to navigate from current page to target page without any other pages visible.

@Composable
fun MyAppNavigation(
    modifier: Modifier, authViewModel: AuthViewModel
) {
    val pages = registerInfoList.size
    val pagerState = rememberPagerState(pageCount = { pages })
    val scope = rememberCoroutineScope()
    val shouldRequestFocus = remember { mutableStateOf(true) }


    Column(
        modifier = modifier.fillMaxSize()
    ) {
        HorizontalPager(
            state = pagerState, userScrollEnabled = false
        ) { page ->
            when (page) {
                0 -> StartPage(modifier = modifier,
                    toSignUp = {
                        scope.launch {
                            pagerState.animateScrollToPage(2)
                        }
                    }, toLogin = {
                        scope.launch {
                            pagerState.animateScrollToPage(1)
                        }
                    }, authViewModel = authViewModel
                )


                1 -> LoginPage(modifier = modifier,
                    toHome = {
                        scope.launch {
                            pagerState.animateScrollToPage(3)
                        }
                    }, toSignUp = {
                        scope.launch {
                            pagerState.animateScrollToPage(2)
                        }
                    },
                    toStart = {
                        scope.launch {
                            pagerState.animateScrollToPage(0)
                        }
                    }, authViewModel = authViewModel
                )


                2 -> SignupPage(
                    modifier = modifier,
                    toStart = {
                        scope.launch {
                            pagerState.animateScrollToPage(0)
                        }
                    },
                    toHome = {
                        scope.launch {
                            pagerState.animateScrollToPage(3)
                        }

                    },

            authViewModel = authViewModel
                )

                3 -> HomePage(modifier = modifier, toStart = {
                    scope.launch {
                        pagerState.animateScrollToPage(0)
                    }
                }, authViewModel = authViewModel)
            }
        }
    }
}

i used scrolToPage, but i want the animation to be visible.


Solution

  • HorizontalPager is not designed to allow skipping pages. In your case, I would recommend using a NavHost instead. You can specify custom enterTransitions and exitTransitions to achieve a similar visual effect as a HorizontalPager scrolling:

    val navController = rememberNavController()
    
    NavHost(
        navController = navController,
        startDestination = "startPage",
        modifier = Modifier.padding(paddingValues)
    ) {
        composable(
            route = "startPage",
            exitTransition = {
                slideOutHorizontally(
                    animationSpec = tween(2000),
                    targetOffsetX = { fullWidth -> -fullWidth }
                )
            }
        ) {
            StartPage(
                modifier = modifier,
                toSignUp = {
                    navController.navigate("signupPage")
                }, 
                toLogin = {
                    navController.navigate("loginPage")
                }, 
                authViewModel = authViewModel
        }
        composable(
            route = "loginPage",
            enterTransition = {
                slideInHorizontally(
                    animationSpec = tween(2000),
                    initialOffsetX = { fullWidth -> fullWidth }
                )
            }
        ) {
            LoginPage(
              //...
            )
        }
        composable(
            route = "signupPage",
            enterTransition = {
                slideInHorizontally(
                    animationSpec = spring(stiffness = Spring.StiffnessHigh),
                    initialOffsetX = { - it / 2 }
                )
            }
        ) {
            SignupPage(
              //...
            )
        }
    }
    

    I set the tween duration to 2000ms for demonstration purposes, please change it according to your needs.