Jetpack Compose 的 Navigation学习

网友投稿 308 2022-08-23

Jetpack Compose 的 Navigation学习

文章目录

​​1. 概述​​​​2. Navgation api​​

​​2.1 使用 `NavHost`​​​​2.2 composable()​​

​​2.2.1 注释1:id​​​​2.2.2 注释2: arguments​​​​2.2.3 注释3:lambda表达式​​

​​2.3 页面跳转​​​​2.4 DeepLink​​​​2.5 嵌套结构​​

​​官网​​

1. 概述

​​Navigation​​ 是 Jetpack 用于 Android 导航的组件,作用是处理页面跳转,以及页面跳转过程中的交互。

使用 ​​Navigation​​,你就需要为每个页面设定一条唯一路径,它是一个 String 常量,形式是 DeepLink 的样子,从一个页面跳转到另一个页面,它通过输入目的地的路径进行转跳。

​​Navigation​​ 也支持上 Compose,我们可以在 Compose 中使用它来进行跳转。

因为官网和所看到的demo都是把它作为跳转能力使用,所以不清楚 Compose 是否还有别的跳转方式…

2. Navgation api

2.1 使用 NavHost

​​NavHost​​​ 可以用来描述导航图,就是可以在上面指定那些可以跳转的页面(像是注册路由一样),如果你需要从一个页面跳到另一个页面,你需要改变路线, ​​NavHost​​ 会触发重组,然后跳转到目的地。

​​NavHost​​​ 的重组是由 ​​NavController​​​ 触发的,它代表了 ​​NavHost​​ 的状态, 是 Navigation 在 Compose 的中心 api, 它有两个作用:

跟踪界面上可组合项的回退栈跟踪界面上每个可组合项的状态

我们通过下面方式创建它:

val navController = rememberNavController()

要使用 ​​NavHost​​​, 必须要绑定一个 ​​NavController​​​,并且通过 ​​startDestination​​ 设置一个默认起始页面:

NavHost(navController = navController, startDestination = "profile") { composable("profile") { Profile(/*...*/) } composable("friendslist") { FriendsList(/*...*/) } /*...*/}

2.2 composable()

上面在 ​​NavHost​​ 中填入的 composable 是什么呢?

​​composable(..) { ... }​​ 是 Navigation 提供的 DSL,它可以让我们添加可导航的页面,一个 composable() 可以视为注册一个可导航页面,就像下面这样:

// 为 Profile 赋予导航能力,相当于注册到路由表上composable( "profile?userId={userId}", // 1 arguments = listOf(navArgument("userId") { defaultValue = "me" }) // 2) { backStackEntry -> // 3 Profile(navController, backStackEntry.arguments?.getString("userId"))}

它一般有三个参数,下面逐一解释。

2.2.1 注释1:id

表示页面的路径,是页面的导航标识,是 String 类型。

可以通过 ​​{...}​​设置占位符,例如例子里面的 userId。

还可以扩展其能力,做为 deeplink,例如跳转到 web 页,具体将在下面讲解。

2.2.2 注释2: arguments

导航目的地的可组合项所需参数,是可选参数, 需要使用 ​​NavArgument​​ 组成的列表携带。

默认情况下,所有参数都会作为字符串被解析, 我们可以通过 type设置。

NavHost(startDestination = "profile/{userId}/{age}") { ... composable( "profile/{userId}/{age}", arguments = listOf( navArgument("userId") { type = NavType.StringType }, // 这里可以不用写,因为默认就是字符串 navArgument("age") { type = NavType.IntType } // 需要显式设置为 Int 类型 ) ) {...}}

我们还可以为 ​​navArgument​​​ 设置别的可选参数,例如 ​​defaultValue​​​ 或 ​​nullability = true​​(默认值可空):

navArgument("userId") { default = "123456" }

2.2.3 注释3:lambda表达式

它是一个用于构造一个可组合项,表示页面内容。看起来是一个 ​​(NavBackStackEntry) -> @Compsable()​​ 类型。

​​NavBackStackEntry​​​ 表示回退栈信息, 它的 ​​argument​​ 携带了打开页面所需要的参数,我们可以使用它来提取参数,然后构造可组合项:

composable("profile/{userId}") { backStackEntry -> Profile(navController, backStackEntry.arguments?.getString("userId"))}

2.3 页面跳转

通过调用 ​​navController.navgate(..)​​ 进行导航, 参数是目的地的标识,如下所示:

@Composablefun Profile(navController: NavController) { /*...*/ Button(onClick = { navController.navigate("friendslist") }) { Text(text = "Navigate next") } /*...*/}

需要注意的是,我们需要在回调中才能使用它,避免在可组合项中直接使用,避免重组时调用了它。

如果我们需要携带参数,可以直接填入:

navController.navigate("profile/user1234")navController.navigate("profile/${getUid()}")

默认情况下, ​​navigate​​ 会将新目的地添加到回退栈中,我们可以通过添加别的参数来改变这个行为:

// 在进入"friendsList"之前,回退栈会弹出所有的可组合项,直到 "home"navController.navigate("friendslist") { popUpTo("home")}// 在进入"friendsList"之前,回退栈会弹出所有的可组合项,直到 "home",并且包括它navController.navigate("friendslist") { popUpTo("home") { inclusive = true }}// 对应 Android 的 SingleTop,如果回退栈顶部已经是 "search",就不会重新创建navController.navigate("search") { launchSingleTop = true}

更多能力请参考: ​​popUpTo 指南​​

2.4 DeepLink

Navigation Compose 支持隐式深层链接,此类链接也可定义为 composable() 函数的一部分。使用 navDeepLink() 以列表的形式添加深层链接。

例如下面代码中定义的导航项,它将页面参数拼接到 deepLink:

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

借助这些深层链接,可以将特定的网址、操作和/或 MIME 类型与可组合项关联起来。

我们可以在 manifest.xml 文件添加相应的 ​​​​​ 元素,使得外部可以访问。如需启用上述深层链接,可以在清单的 ​​​​ 元素中添加以下内容:

...

当其他应用触发该深层链接时,Navigation 会自动深层链接到相应的可组合项。

这些深层链接还可用于构建包含可组合项中的相关深层链接的 ​​PendingIntent​​:

val id = "exampleId"val context = LocalContext.currentval deepLinkIntent = Intent( Intent.ACTION_VIEW, " context, MyActivity::class.java)val deepLinkPendingIntent: PendingIntent? = TaskStackBuilder.create(context).run { addNextIntentWithParentStack(deepLinkIntent) getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)}

2.5 嵌套结构

一个 ​​NavHost​​​ 内注册的可组合项看起来是平铺的,没有深层结构。 我们可以通过 ​​navigation​​ 函数为其增加嵌套内容。

例如下面定义一个导航结构, “login” 可组合项又可以导航到 “username”、“password”、“registration” 这三个可组合项,而不让别的与 login 同级的可组合项进入,我们可以这样写:

NavHost(navController, startDestination = "home") { ... // 通过 route 来为'login' 定义一个更深层次的导航图 // 因此'username'封装了图的内部路由逻辑 navigation(route = "login", startDestination = "username") { composable("username") { ... } composable("password") { ... } composable("registration") { ... } } ...}

官方建议,如果在导航图比较大时,将其作为扩展函数拆分一下,以调高代码可读性:

fun NavGraphBuilder.loginGraph(navController: NavController) { navigation(startDestination = "username", route = "login") { composable("username") { ... } composable("password") { ... } composable("registration") { ... } }}// 使用:NavHost(navController, startDestination = "home") { ... loginGraph(navController) ...}

官网

​​使用 Compose 进行导航​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【C++】~的使用简介
下一篇:Python 优雅的操作字典(python的析构方法是)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~