如何在使用Jetpack Compose + Navigation(无需片段)时处理后退导航。

15

我试图从引导界面导航到仪表板及更多页面,并在用户访问仪表板后关闭引导页面,但是当我使用“返回操作”时,又回到了引导页面。

这里是示例代码:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MainUI()
        }
    }
}

@Composable
fun MainUI() {
    val navController = rememberNavController()

    NavHost(
        navController = navController,
        startDestination = "onboarding"
    ) {
        composable("onboarding") {
            Column {
                Text("I am on onboarding")
                Button(onClick = {
                    navController.navigate("dashboard") {
                        popUpTo("dashboard") // I want to get rid of onboarding here
                    }
                }) {
                    Text("go to dashboard")
                }
            }
        }
        composable("dashboard") {
            Column {
                Text("I am on dashboard")
                Button(onClick = {
                    navController.navigate("detail")
                }) {
                    Text("go to detail")
                }
            }
        }
        composable("detail") {
            Text("I am on detail")
        }
    }
}

这个也不起作用

navController.navigate("dashboard") {
    popUpTo("dashboard") {
            inclusive = true // no difference
        }

// ....

    popUpTo("onboarding") // also nothing

// ....

    popUpTo("onboarding") {
            inclusive = true // this crashes -> NavGraph cannot be cast to ComposeNavigator$Destination
        }

}


由于某些原因,这种方法是有效的,所以仪表板被关闭,我从详细信息页转到了引导页面。
navController.navigate("detail") {
     popUpTo("dashboard") {
            inclusive = true
     }
}
4个回答

34

我觉得我的解决方案非常简单,如果我错了,请指点我。

navController.popBackStack()

你是如何实例化 navController 的? - undefined

14
您可以使用BackHandler 链接
@Composable
    fun TestScreen() {
        BackHandler {
             // code
            // example - activity.finish()
        }
    }

1
我不认为它起作用,BackHandler 只有在最后一次导航退出应用程序时才会被拦截。如果我错了,请纠正我。 - undefined

1

好的,我已经自己找到了一个可行的解决方案,但我仍然不确定是否需要这个“样板代码”:( 但是这个代码按照预期工作,也就是说,一旦从页面导航离开,它就会被关闭。

NavHost(
        navController = navController,
        startDestination = "onboarding"
    ) {
        navigation(
            startDestination = "onboardingUI",
            route = "onboarding"
        ) {
            composable("onboardingUI") {
                Column {
                    Text("I am on onboarding")
                    Button(onClick = {
                        navController.navigate("dashboard"){
                            popUpTo("onboarding")
                        }
                    }) {
                        Text("go to dashboard")
                    }
                }
            }
        }
        navigation(startDestination = "dashboardUI", route = "dashboard") {
            composable("dashboardUI") {
                Column {
                    Text("I am on dashboard")
                    Button(onClick = {
                        navController.navigate("detail"){
                            popUpTo("dashboard")
                        }
                    }) {
                        Text("go to detail")
                    }
                }
            }
        }
        navigation(startDestination = "detailUI", route = "detail") {
            composable("detailUI") {
                Text("I am on detail")
            }
        }
    }
}

注意: routestartDestination(亦称为组合的名称)不能相同。


2
你只需要深入思考一下就行了 ;) - Richard Onslow Roper

1

正如@James Christian Kaguo所说,navController.popBackStack()是一种选择。但是在使用此方法时必须小心。由于某些原因,后退队列的大小至少为2,如果弹出的后退栈小于该值,则导航似乎不再起作用。

因此,我编写了以下简单的扩展函数:

fun NavController.navigateBack() {
    if (backQueue.size > 2) {
        popBackStack()
    }
}

从navigation-compose:2.6.0版本开始,backqueue是私有的。 - Patrick Valsecchi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接