当前位置:网站首页>Jetpack Compose 的 Navigation学习
Jetpack Compose 的 Navigation学习
2022-08-08 17:30:00 【RikkaTheWorld】
文章目录
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(..)
进行导航, 参数是目的地的标识,如下所示:
@Composable
fun 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 = "https://www.example.com"
composable(
"profile?id={id}",
deepLinks = listOf(navDeepLink {
uriPattern = "$uri/{id}" })
) {
backStackEntry ->
Profile(navController, backStackEntry.arguments?.getString("id"))
}
借助这些深层链接,可以将特定的网址、操作和/或 MIME 类型与可组合项关联起来。
我们可以在 manifest.xml 文件添加相应的 <intent-filter>
元素,使得外部可以访问。如需启用上述深层链接,可以在清单的 <activity>
元素中添加以下内容:
<activity …>
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
</intent-filter>
</activity>
当其他应用触发该深层链接时,Navigation 会自动深层链接到相应的可组合项。
这些深层链接还可用于构建包含可组合项中的相关深层链接的 PendingIntent
:
val id = "exampleId"
val context = LocalContext.current
val deepLinkIntent = Intent(
Intent.ACTION_VIEW,
"https://www.example.com/$id".toUri(),
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)
...
}
官网
边栏推荐
猜你喜欢
信号生成和可视化
转载,fragment讲的很好的大佬
2 prerequisites for the success of "digital transformation" of enterprises!
字节一面:TCP 和 UDP 可以使用同一个端口吗?
【CC3200AI 实验教程4】疯壳·AI语音人脸识别(会议记录仪/人脸打卡机)-GPIO
KITTI数据集简介(一)—— 传感器介绍
离线安装 Anaconda + TensorFlow
无需精子卵子子宫体外培育胚胎,Cell论文作者这番话让网友们炸了
【20210923】选择感兴趣的研究方向?
Open source summer | I have nothing to do during the epidemic, I made a button display box special effect to display my blog
随机推荐
TCP协议详解
DSPE-PEG-Biotin,385437-57-0,磷脂-聚乙二醇-生物素用于生物分子的检测和纯化
套接字的概念
PNAS最新研究:81%解题率,神经网络 Codex 推开高等数学世界大门
史上最强IDEA工具使用教程,你想要的全都有!
dp,dpi,px知识补充
LeetCode_Binary Tree_Medium_515. Find the maximum value in each tree row
1.初识MySQL数据库
Tensorflow教程(六)——变量基础操作
Basic knowledge of software engineering, software engineering
Getting started with glide4
转载,fragment讲的很好的大佬
arm交叉编译
【数学模型】TOPSIS
文件操作和IO
Obtain - 64 [chances] : the soldier, subtlety also - 5 - read sun tzu - melee meter
Detailed explanation of JVM memory model and structure (five model diagrams)
WPF StepBar
Are Huishang Futures official and reliable?Is it safe to open an account in Huishang Futures?
【TypeScript】函数类型:返回值类型和参数类型到底如何定义?