简体   繁体   English

Jetpack Compose:导航到 X 屏幕(跳转)保持回栈历史

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

Have Activity which holds NavHostController , when activity starts need to navigate X screen but pressing back need to navigate to previous screen not to start destination.拥有包含NavHostControllerActivity ,当 Activity 开始时需要导航 X 屏幕但按下返回需要导航到上一个屏幕而不是开始目的地。

@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"有这样的屏幕:“屏幕 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)并且“屏幕1”是开始目的地,活动开始并且nav-ctrl跳转到屏幕5(例如),并且后按需要像:到4、3、2..而不是直接1(因为开始目的地是1)

Question: How to set back stack history in nav controller OR How navigate (jump) with keeping back stack order.问题:如何在导航 controller 中设置回退堆栈历史记录或如何在保持回退堆栈顺序的情况下导航(跳转)。

To achieve this you will need to use the BackHandler and make some check to see if the previous back stack route is the screen that should be the destination when using the back button.为了实现这一点,您需要使用BackHandler并检查前一个返回堆栈路由是否是使用返回按钮时应该成为目的地的屏幕。 For example:例如:

@Composable
fun ScreenOne(
    nextScreen: () -> Unit
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "ScreenOne")

        Button(onClick = nextScreen) {
            Text(text = "Next")
        }
    }
}
@Composable
fun ScreenTwo(
    back: () -> Unit,
    nextScreen: () -> Unit
) {
    // to intercept the click on the back button of the android navigation bar
    BackHandler(onBack = back)

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "ScreenTwo")

        Button(onClick = back) {
            Text(text = "Back")
        }

        Button(onClick = nextScreen) {
            Text(text = "Next")
        }
    }
}
@Composable
fun ScreenThree(
    back: () -> Unit
) {
    // to intercept the click on the back button of the android navigation bar
    BackHandler(onBack = back)

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "ScreenThree")

        Button(onClick = back) {
            Text(text = "Back")
        }
    }
}

ScreenOne just have the option to navigate to ScreenTwo . ScreenOne只能选择导航到ScreenTwo
ScreenTwo have the option to navigate (back) to ScreenOne and navigate to ScreenThree . ScreenTwo可以选择导航(返回)ScreenOne并导航到ScreenThree
ScreenThree just have the option to navigate (back) to ScreenTwo . ScreenThree只能选择导航(返回)ScreenTwo

Extension to navigate back:向后导航的扩展:

fun NavHostController.navigateBack(
    targetRoute: String,
    currentRoute: String
) {
    val previousRoute = previousBackStackEntry?.destination?.route ?: "null"

    // if the previous route is what we want, just go back
    if (previousRoute == targetRoute) popBackStack()
    // otherwise, we do the navigation explicitly
    else navigate(route = targetRoute) {
        // remove the entire backstack up to this this route, including herself
        popUpTo(route = currentRoute) { inclusive = true }
        launchSingleTop = true
    }
}

NavHost:导航主机:

NavHost(
    modifier = Modifier.fillMaxSize(),
    navController = navController,
    startDestination = "screen_three"
) {
    composable(route = "screen_one") {
        ScreenOne(
            nextScreen = {
                navController.navigate(route = "screen_two") {
                    launchSingleTop = true
                }
            }
        )
    }

    composable(route = "screen_two") {
        ScreenTwo(
            back = {
                navController.navigateBack(
                    targetRoute = "screen_one",
                    currentRoute = "screen_two"
                )
            },
            nextScreen = {
                navController.navigate(route = "screen_three") {
                    launchSingleTop = true
                }
            }
        )
    }

    composable(route = "screen_three") {
        ScreenThree(
            back = {
                navController.navigateBack(
                    targetRoute = "screen_two",
                    currentRoute = "screen_three"
                )
            }
        )
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM