在 Android/Jetpack Compose 中手动预填充导航后台

问题描述 投票:0回答:2

是否可以在 Android/Jetpack Compose 中预填充导航后台?

我有一个深层链接,可以深入导航层次结构,但是,按后退时,它会导航到根路线。

示例:

Route.Main -> Route.List -> Route.Details(参数:id)

深层链接: https://mywebsite.com/details/id

当前行为: 它使用正确的参数打开 Route.Details,但是,在 onBack 时,它打开 Route.Main

期望的行为: 它应该打开 Route.List

我知道我可以手动“编程”此行为,但我更愿意“配置”它。

android android-jetpack-compose android-navigation jetpack-compose-navigation
2个回答
1
投票

我以前也遇到过类似的问题,似乎这是图书馆的预期行为。我的意思是,如果用户从显示 Screen_C 的深层链接打开应用程序,然后按返回,则应显示应用程序的主屏幕。所以也许您需要重新验证应用程序的可用性。

但是,即使您想解决手动处理后压的问题。使用下面的功能

fun navigatingBack(
    navController: NavHostController,
    destinationRoute: String
) {
    val hasBackstackTheDestinationRoute = navController.backQueue.find {
        it.destination.route == destinationRoute
    } != null
    // if the destination is already in the backstack, simply go back
    if (hasBackstackTheDestinationRoute) {
        navController.popBackStack()
    } else {
        // otherwise, navigate to a new destination popping the current destination
        navController.navigate(destinationRoute) {
            navController.currentBackStackEntry?.destination?.route?.let {
                popUpTo(it) {
                    inclusive = true
                }
            }
        }
    }
}

假设您声明了屏幕

ScreenA
ScreenB
ScreenC

composable("__A__") {
    ScreenA(navController)
}
composable("__B__") {
    ScreenB(navController)
}
composable("__C__") {
    ScreenC(navController)
}

您可以执行以下操作:

@Composable
fun ScreenA(navController: NavHostController) {
    Button(onClick = {
        navController.navigate("__B__")
    }) {
        Text(text = "Screen A - Go to B")
    }
}

@Composable
fun ScreenB(navController: NavHostController) {
    Button(onClick = {
        navController.navigate("__C__")
    }) {
        Text(text = "Screen B - Go to C")
    }
    BackHandler {
        navigatingBack(navController, "__A__")
    }
}

@Composable
fun ScreenC(navController: NavHostController) {
    Text(text = "Screen C")
    BackHandler {
        navigatingBack(navController, "__B__")
    }
}

使用上面的示例,如果您直接导航到

ScreenC
并按返回,则会显示
ScreenB
。类似的情况也发生在
ScreenB
中,按下后退按钮时会显示
ScreenA


0
投票

要使用较新版本的

navigation-compose
更新 @nglauber 的答案,您不再有权访问
navController.backQueue
,我建议像这样扩展
NavHostController

/**
 * Attempt to pop up to the destination. If the destination is present
 * in the back stack then it will pop up to it. If the destination
 * is not present in the back stack it will navigate to it and remove
 * the current screen from the stack.
 */
fun NavHostController.popUpTo(route: String) {
  try {
    this.getBackStackEntry(route)
    popBackStack(route, false)
  } catch (exception: IllegalArgumentException) {
    navigate(route) {
      currentBackStackEntry?.destination?.route?.let {
        popUpTo(it) {
          inclusive = true
        }
      }
    }
  }
}

然后,当你想使用它时,它会被简化为

BackHandler {
  navController.popUpTo("__A__")
}
© www.soinside.com 2019 - 2024. All rights reserved.