簡體   English   中英

Jetpack Compose:導航到 X 屏幕(跳轉)保持回棧歷史

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

擁有包含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") {}
}}

例子:

有這樣的屏幕:“屏幕 1-2-3-4-5..N”

並且“屏幕1”是開始目的地,活動開始並且nav-ctrl跳轉到屏幕5(例如),並且后按需要像:到4、3、2..而不是直接1(因為開始目的地是1)

問題:如何在導航 controller 中設置回退堆棧歷史記錄或如何在保持回退堆棧順序的情況下導航(跳轉)。

為了實現這一點,您需要使用BackHandler並檢查前一個返回堆棧路由是否是使用返回按鈕時應該成為目的地的屏幕。 例如:

@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只能選擇導航到ScreenTwo
ScreenTwo可以選擇導航(返回)ScreenOne並導航到ScreenThree
ScreenThree只能選擇導航(返回)ScreenTwo

向后導航的擴展:

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(
    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