Narek Hayrapetyan
Narek Hayrapetyan

Reputation: 1929

Jetpack Compose: navigate to X screen (jump) keeping back-stack history

Have an Activity which holds NavHostController, when activity starts, need to navigate X screen, but pressing back need to navigate to previous screen, not to the start destination (because navigating to X was from startDest).

@OptIn(ExperimentalMaterialNavigationApi::class)
@Composable
private fun NavHostController(
    navController: NavHostController,
    startDest: String = "screen 1"
) {
    NavHost(
        navController = navController,
        startDestination = startDest,
    ) {
        composable("screen 1") {}
        composable("screen 2") {}
        ...
        composable("screen N") {}
}}

EXAMPLE:

have screens like: "screen 1-2-3-4-5..N"

and the "screen 1" is start destination, activity starts and nav-ctrl jumps to screen 5(for example), and the back press need to work like: to 4, 3, 2.. NOT direct 1 (as start destination is 1)

Question: How to set back stack history in nav controller OR How navigate (jump) with keeping back stack order.

Upvotes: 2

Views: 2641

Answers (1)

Narek Hayrapetyan
Narek Hayrapetyan

Reputation: 1929

OK actually solved this issue using view-pager see here

So It can jump easily any screen on View-pager as current page,

LaunchedEffect(
        key1 = currentPage,
        block = {
            pagerState.animateScrollToPage(currentPage)
        })

and overrides back button and action to go back through view-pager pages (currentPage-1) if current page. is 0, then closes whole screen (activity).

Also disabled user events on view-pager to not allow change page with swiping, set userScrollEnabled to false.

userScrollEnabled: Boolean = false

BUT Second solution using navigation.

    private const val STEPS: String = "steps"
    private const val CURRENT_STEP: String = "currentStep"
    private const val PATH: String = "your_screen/{$STEPS}/{$CURRENT_STEP}"

    @Composable
    fun MyComposable() {
        val navController = rememberNavController()
        NavHost(
            navController = navController,
            startDestination = PATH,
            modifier = modifier.fillMaxSize(),
        ) {
            composable(
                route = PATH,
                arguments = listOf(
                    navArgument(CURRENT_STEP) {
                        type = NavType.IntType
                        defaultValue = 0
                    },
                )
            ) { backStackEntry ->
                PagesScreen(
                    navController = navController,
                    currentStep = backStackEntry.arguments?.getInt(CURRENT_STEP) ?: 0,
                )
            }
        }    
    }

@Composable
private fun PagesScreen(
    navController: NavController,
    modifier: Modifier = Modifier,
    currentStep: Int = 0,
    onFinish: () -> Unit = {},
) {
    val stepsCount = 6 // your navigation steps pages count
   // show current page

    val goToNextScreen = {
        if (currentStep < stepsCount - 1) {
            navController.navigate("your_screen/$stepsCount/${currentStep + 1}")
        } else {
          onFinish()
        }
    }
    val goToPreviousScreen = {
        if (currentStep > 0) {
            navController.navigate("your_screen/$stepsCount/${currentStep - 1}")
        } else {
          onFinish()
        }
    }
}

Upvotes: 1

Related Questions