xsh*_*ake 13 navigation android kotlin android-jetpack-navigation android-jetpack-compose
我正在开发 Jetpack Compose Navigation 演示,并且有一个嵌套导航图,其中包含两个不同的嵌套路线以及每个嵌套路线的屏幕:
登录图具有三种路线,用于显示三个不同的屏幕
主图有两个用于这些屏幕的路线
嵌套图创建在MainActivity.kt中调用
setContent {
NavigationDemoTheme {
val navController = rememberNavController()
SetupNavGraph(navController = navController)
}
}
Run Code Online (Sandbox Code Playgroud)
文件NestedNavGraph.kt中的函数如下所示:
fun SetupNavGraph(navController: NavHostController) {
NavHost(navController = navController, startDestination = "login_route")
{
loginGraph(navController = navController)
mainGraph(navController = navController)
}
}
Run Code Online (Sandbox Code Playgroud)
在文件LoginNavGraph.kt中,我定义了路线和起始目的地
fun NavGraphBuilder.loginGraph(navController: NavController) {
navigation(startDestination = "login", route = "login_route") {
composable(route = "login") {
LoginScreen(navController = navController)
}
composable(route = "register") {
RegisterScreen(navController = navController)
}
composable(route = "recover") {
RecoverPasswordScreen(navController = navController)
}
}
}
Run Code Online (Sandbox Code Playgroud)
在文件MainNavGraph.kt中,我定义了这两条路线和这个起始目的地:
navigation(startDestination = "home", route = "main_route") {
composable(route = "home") {
HomeScreen(navController = navController)
}
composable(route = "settings") {
SettingsScreen(navController = navController)
}
}
Run Code Online (Sandbox Code Playgroud)
我现在的问题是:如何从设置屏幕显示恢复密码屏幕。我知道我可以从 SettingsScreen 导航到“login_route”,但随后将显示 startDestination,即 LoginScreen。
// shows the LoginScreen because the startDestination in the "login_route" is set to "login"
navController.navigate(route = "login_route")
Run Code Online (Sandbox Code Playgroud)
那么,如何直接导航到嵌套图路由“login_route”中的路由“recover”?我想到了以下“解决方法”:
将参数传递给“login_route”,例如:
navController.navigate(route = "login_route?destination=recover")
Run Code Online (Sandbox Code Playgroud)
然后,我将只有一条路线作为目的地,例如“LoginView”。这将改变登录图,如下所示:
fun NavGraphBuilder.loginGraph(navController: NavController) {
navigation(startDestination = "login_view, route = "login_route/{destination}) {
composable(
route = "login_view",
arguments = listOf(
navArgument("destination") { defaultValue = "login" },
)
) { backStackEntry ->
val destination = backStackEntry.arguments?.getString("destination");
destination?.let { destination ->
LoginView(destination = destination)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
LoginView 是可组合的,它将有一个自己的 NavHost,我可以在其中使用上一个路由中的查询参数设置 startDestination:
fun LoginView( destination : String = "login"){
val navController = rememberNavController()
var startDestination = destination;
Scaffold ()
{
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(route = "login") {
LoginScreen(navController = navController)
}
composable(route = "register") {
RegisterScreen(navController = navController)
}
composable(route = "recover") {
RecoverPasswordScreen(navController = navController)
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我应该能够通过以下命令从 SettingsScreen 调用 RecoverPasswordScreen:
navController.navigate(route = "login_route?destination=recover")
Run Code Online (Sandbox Code Playgroud)
另一种可能性是在定义的 MainGraph 中为 RecoverPassword Screen 提供额外的路由。是否有其他可能性可以直接访问嵌套图中的路线?如果可以在路由到“login_route”时动态更改 startDestination 那就太好了,但我不知道如何或是否可能这样做。
Fer*_*nd -1
Compose 允许您(使用参数导航)。这允许您导航到所谓的“嵌套路由”,即屏幕中的特定部分。
现在,这是一个简单的解释,我可以离开你并让你弄清楚。但我认为这对您没有帮助,因为我认为您已经以困难的方式实现了导航。因此,为什么尝试导航会更复杂一些。
这是一种更好的实现方法,以便您想要的导航(从设置屏幕恢复密码屏幕)更容易。
将Main中的任何内容更改为您的 AppName。
我还没有添加你所有的屏幕
//you could pass in parameters if needed into this constructor
enum class MainScreen(){
//these are your screens
LogIn(),
Settings(),
Recover(),
Home();
companion object {
fun fromRoute(route: String?): MainScreen =
when (route?.substringBefore("/")) {
LogIn.name -> LogIn
Home.name -> Home
Settings.name -> Settings
Recover.name -> Recover
//add the remaining screens
// a null route resolves to LogInScreen.
null -> LogIn
else -> throw IllegalArgumentException("Route $route is not recognized.")
}
}
}
Run Code Online (Sandbox Code Playgroud)
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainApp()
}
}
}
@Composable
fun MainApp() {
MainTheme {
val allScreens = MainScreen.values().toList()
val navController = rememberNavController()
val backStackEntry = navController.currentBackStackEntryAsState()
// currentScrren user is on good if app is large
val currentScreen = MainScreen.fromRoute(
backStackEntry.value?.destination?.route
)
//Using scaffold is a good idea
Scaffold(
//add topAppBar and all other things here
) { innerPadding ->
MainNavHost(navController = navController, modifier = Modifier.padding(innerPadding))
}
}
}
//Scaffold requires innerPadding so remove if you decide not to use scaffold
@Composable
fun MainNavHost(navController: NavHostController, modifier: Modifier = Modifier) {
NavHost(
navController = navController,
startDestination = LogIn.name,
modifier = modifier
) {
composable(LogIn.name) {
/**
Your body for logIn page
**/
}
//this is how you will navigate to Recover Screen from settings
composable(Settings.name) {
SettingsBody(onClickRecoverScreen = {navController.navigate(Recover.name)})
}
}
composable(Recover.name) {
/**
Your body for Recover page
**/
}
composable(Home.name) {
/**
Your body for Home page
**/
}
}
Run Code Online (Sandbox Code Playgroud)
@Composable
fun SettingsBody(
//this callback is how you will navigate from Settings to RecoverPassword
onClickRecoverScreen: () -> Unit = {},
) {
Column(
//Add your designs for this screen
) {
Button(onClick = {onClickRecoverScreen})
}
}
Run Code Online (Sandbox Code Playgroud)
这是实现导航的最简单的方法(在我看来),因为您可以简单地添加回调来导航到应用程序中的不同位置,并且它更具可测试性(如果您测试;))和可扩展性。您还可以添加深层链接并使用参数(如上所述)导航到应用程序的特定部分(例如,帐户屏幕中的特定帐户)
如果您想了解更多信息,我强烈推荐这个导航代码实验室。
| 归档时间: |
|
| 查看次数: |
10974 次 |
| 最近记录: |