Jetpack Compose 导航:从具有相同路线(参数除外)的屏幕弹出到屏幕

Sae*_* Oh 8 android kotlin android-jetpack-navigation android-jetpack-compose android-jetpack-compose-scaffold

导航撰写版本2.4.0-alpha06

我有一个导航抽屉Scaffold,其中部分项目是由 ViewModel 动态生成的。

示例项目有

  • A
  • C ...
  • 设置

其中 A、B、C... 都共享相同的Screencalled Category,只是传递了不同的参数(例如 Category/A、Category/B)。

在我的里面Scaffold

...

val items = viewModel.getDrawerItems()
// This gives something like 
// ["Home", "Category/A", "Category/B", "Category/C", ..., "Settings"] 
// where each String represents "route"

...

val backstackEntry = navController.currentBackStackEntryAsState()
val currentScreen = Screen.fromRoute(
    backstackEntry.value?.destination?.route
)
Log.d("Drawer", "currentScreen: $currentScreen")

items.forEach { item ->
    DrawerItem(
        item = item, 
        isSelected = currentScreen.name == item.route, 
        onItemClick = {
            Log.d("Drawer", "destinationRoute: ${item.route}")
            navController.navigate(item.route)
            scope.launch {
                scaffoldState.drawerState.close()
            }
        }
    )
}
Run Code Online (Sandbox Code Playgroud)

这段代码工作得很好,除了当我访问主屏幕时,我想清除所有返回堆栈到主页(不包括在内)。

我尝试过添加NavOptionsBuilder

...

navController.navigate(item.route) {
    popUpTo(currentScreen.name) {
        inclusive = true
        saveState = true
    }
}
...
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为currentScreen.name会给出类似的内容Category/{title},并且 popUpTo 仅尝试从后堆栈中查找完全匹配的内容,因此它不会弹出任何内容。

有真正的组合导航方法来解决这个问题吗?或者我应该将最后一个“标题”保存在 ViewModel 中的某个位置并使用它?

Google 的这个教程具有类似的结构,但它只是堆叠屏幕,因此从屏幕 A -> B -> A 返回并单击“返回”只会返回到 B -> A,这对我来说不是理想的行为。

先感谢您。

Sha*_*auf 8

您可以创建一个扩展函数来在所有地方提供popUpTo功能。

fun NavHostController.navigateWithPopUp(
    toRoute: String,  // route name where you want to navigate
    fromRoute: String // route you want from popUpTo.
) {
    this.navigate(toRoute) {
        popUpTo(fromRoute) {
            inclusive = true // It can be changed to false if you
                             // want to keep your fromRoute exclusive
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

navController.navigateWithPopUp(Screen.Home.name, Screen.Login.name)
Run Code Online (Sandbox Code Playgroud)


Phi*_*hov 6

当您指定时,popUpTo您应该传递您在这种情况下导航到的相同项目:

navController.navigate(item.route) {
    popUpTo(item.route) {
        inclusive = true
    }
}
Run Code Online (Sandbox Code Playgroud)

也不确定在这种情况下是否需要指定saveState,这取决于您:

NavOptionsBuilder.popUpTo是否应保存当前目的地和 ID 之间的返回堆栈和所有目的地的状态,以供以后NavOptionsBuilder.restoreState通过使用相同NavOptionsBuilder.popUpToID 的 RestoreState 属性进行恢复(注意:无论 Include 为 true 或 false,此匹配 ID 均为 true)。