[英]Navigate from Jetpack Compose to Fragment and from Fragment to Jetpack Compose Screen
[英]Jetpack Compose: navigate to X screen (jump) keeping back-stack history
擁有包含NavHostController
的Activity
,當 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.