Compose之Navigation使用(带参数)

1,255 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情 Screen Shot 2022-11-25 at 7.45.10 PM.png

昨天简单的看了compose的navigation使用,今天看看navigation带参数的例子,看下面简单的例子: 1.定义:

@Composable
fun AppNavHost() {
    val navControl = rememberNavController()
  NavHost(navController = navControl, startDestination = Destinations.Screen1.route ){
      composable(Destinations.Screen1.route){
          ScreenPage1(navControl)
      }
      composable("${Destinations.Screen2.route}/{name}", arguments = listOf(navArgument("name" ){ type = NavType.StringType
      })){ backStackEntry ->
          backStackEntry.arguments?.getString("name")?.let { ScreenPage2(it) }
      }
  }
}

上面定义了两个导航页面,ScreenPage1是起始页没有参数,第二个页面就带参数了,参数的写法就是Destination+/+{参数名称},然后在arguments里面详细定义参数参数的类型。这里也可以设置默认值。

使用的地方:

@Composable
fun ScreenPage1(navController: NavController){
    Text(text = "First screen")
    Button(onClick = { navController.navigate("${Destinations.Screen2.route}/amy") }) {

    }
}

从上面可以看出,只要把参数跟到Destination后面就可以了。那问题来了,如果我有两个以上的参数该怎么办呢? 你从上面的arguments的类型就可以看到,它是支持多参数的,但是写法上稍微会有一些变化:

@Composable
fun AppNavHost() {
    val navControl = rememberNavController()
  NavHost(navController = navControl, startDestination = Destinations.Screen1.route ){
      composable(Destinations.Screen1.route){
          ScreenPage1(navControl)
      }
      composable("${Destinations.Screen2.route}?name={name}&age={age}",
          arguments = listOf(
              navArgument("name" ){ type = NavType.StringType },
              navArgument("age"){type= NavType.IntType})){ backStackEntry ->
          val myName = backStackEntry.arguments?.getString("name") ?: ""
          val age = backStackEntry.arguments?.getInt("age") ?: 9
         ScreenPage2(myName,age)
      }
  }
}

首先是Destination那里有了变化支持变成了:Destination+?+{名称=参数值的key}&{名称=参数值的key}所有的参数用&连接上就可以了。相应的navArgument也会添加相应的参数类型。

使用的地方也是有一点变化的:

@Composable
fun ScreenPage1(navController: NavController){
    Text(text = "First screen")
    Button(onClick = { navController.navigate("${Destinations.Screen2.route}?name=amy&age=23") }) {

    }
}

使用的地方也是跟着定义的地方稍微的发生了一点变化,也是Destination+?+{名称=参数值}&{名称=值}。这样传感觉和html的get方法传参有点像。

但是问题又来了,我能不能传我自定义的类型,也是可以传的,但是官方是不建议传递复杂类型的参数,建议将复杂类型的关键信息传递。

除了上面的传递方式,compose的navigation还传递隐士传参,这里叫做:DeepLink。这里就直接看官方的例子了:

val uri = "https://www.example.com"

composable(
    "profile?id={id}",
    deepLinks = listOf(navDeepLink { uriPattern = "$uri/{id}" })
) { backStackEntry ->
    Profile(navController, backStackEntry.arguments?.getString("id"))
}

DeepLink里面传的是一个uri的值,和使用activity的隐士传参差不多,当然隐士传参需要一个目的地了:

<activity …>
<intent-filter>
<data android:scheme="https" android:host="www.example.com" />
</intent-filter>
</activity>

这样定义完成之后navigation就会自动跳转到这里来了。

关于复杂数据的传递,还需要自己动手试一试哦^_^