IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Jetpack Compose之 在Compose中使用Navigation导航 -> 正文阅读

[移动开发]Jetpack Compose之 在Compose中使用Navigation导航

前言

大约在一年半前,我发布了Compose的第一篇文章?Jetpack Compose开篇 之 HelloWorld,连我自己也没想到,这一年半的时间中我竟再也没有看过Compose..., 如今Compose已经发布了稳定版本,还没学会Compose让我的头发又白了许多~

使用Navigation在Compose中导航

如果你之前不喜欢Android提倡的”单Activity“应用,那么在Compose中相信你会慢慢习惯的~

在此示例中,有两个页面PageOne和PageTwo,首先来看PageOne的代码如下所示:

@Composable
fun PageOne() {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight()
            .background(
                Color.White
            )
    ) {
        Text(text = "这是页面1")
        Spacer(modifier = Modifier.height(20.dp))
        Button(onClick = {
            //点击跳转到页面2
        }) {
            Text(
                text = "跳转页面2",
                modifier = Modifier.fillMaxWidth(),
                textAlign = TextAlign.Center
            )
        }
    }
}

PageOne页面中有个按钮,点击按钮跳转到页面2,为了便于区分,添加一个Text用来显示当前页面内容。

接着来看PageTwo的代码,如下所示:

@Composable
fun PageTwo() {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight()
            .background(
                Color.White
            )
    ) {
        Text(text = "这是页面2")
        Spacer(modifier = Modifier.height(20.dp))
        Button(onClick = {
            //点击返回页面1
        }) {
            Text(
                text = "返回页面1",
                modifier = Modifier.fillMaxWidth(),
                textAlign = TextAlign.Center
            )
        }
    }
}

MainActivity代码如下所示:

setContent?{
????NavigationTheme?{
????????//?A?surface?container?using?the?'background'?color?from?the?theme
????????Surface(color?=?MaterialTheme.colors.background)?{
????????????PageOne()
????????}
????}
}

运行程序,显示出页面1 ,如图所示。

接下来我们来看,如何使用navigation来进行页面导航呢?

定义NavHost

首先我们定义一个NavHost对象

@Composable
fun?NavHostDemo()?{

????NavHost(navController?=,?startDestination?=)?{

????}

}

NavHost对象需要两个必传参数,一个是NavController,一个是起始路由地址,NavController?对象是 Navigation 组件的中心 API,我们可以通过?rememberNavController创建,代码如下所示:

val?navController?=?rememberNavController()

为了便于管理路由地址,我们新建RouteConfig配置文件,代码如下所示:

object?RouteConfig?{

????/**
?????*?页面1路由
?????*/
????const?val?ROUTE_PAGEONE?=?"pageOne"

????/**
?????*?页面1路由
?????*/
????const?val?ROUTE_PAGETWO?=?"pageTwo"
}

在这里,将页面1路由设置为起始导航,并使用composable方法添加导航对应关系,修改后的NavHostDemo代码如下所示:

@Composable
fun?NavHostDemo()?{

????val?navController?=?rememberNavController()
????NavHost(navController?=?navController,?startDestination?=?RouteConfig.ROUTE_PAGEONE)?{

????????composable(RouteConfig.ROUTE_PAGEONE)?{
????????????OnePage()
????????}

????????composable(RouteConfig.ROUTE_PAGETWO)?{
????????????PageTwo()
????????}
????}

}

如此一来,我们就建立了导航对应关系,RouteConfig.ROUTE_PAGEONE对应OnePage,RouteConfig.ROUTE_PAGETWO对应PageTwo,由于我们需要在各自的页面中进行页面跳转,所以将navController传递到对应的页面中去,代码如下所示:

composable(RouteConfig.ROUTE_PAGEONE)?{
????PageOne(navController)
}

composable(RouteConfig.ROUTE_PAGETWO)?{
????PageTwo(navController)
}

这样我们就可以在页面1中进行页面跳转了。

普通页面跳转

修改页面1的代码如下所示:

@Composable
fun?PageOne(navController:?NavController)?{
????Column(
????????modifier?=?Modifier
????????????.fillMaxWidth()
????????????.fillMaxHeight()
????????????.background(
????????????????Color.White
????????????)
????)?{
????????Text(text?=?"这是页面1")
????????Spacer(modifier?=?Modifier.height(20.dp))
????????Button(onClick?=?{
????????????//点击跳转到页面2
????????????navController.navigate(RouteConfig.ROUTE_PAGETWO)
????????})?{
????????????Text(
????????????????text?=?"跳转页面2",
????????????????modifier?=?Modifier.fillMaxWidth(),
????????????????textAlign?=?TextAlign.Center
????????????)
????????}
????}
}

我们在按钮的监听事件中调用navController.navigate方法,传入页面2的路由地址,这样就可以跳转到页面2了。在页面2中调用popBackStack方法将当前页面出栈便又回到了页面1,这里就不贴页面2的代码了。当然我们要记得最后一步:在入口处调用?NavHostDemo()

setContent?{
????NavigationTheme?{
????????//?A?surface?container?using?the?'background'?color?from?the?theme
????????Surface(color?=?MaterialTheme.colors.background)?{
????????????NavHostDemo()
????????}
????}
}

运行程序,点击跳转页面2按钮,在页面2 点击返回页面1按钮,效果如下图所示。

这样一来,我们就实现了?普通页面跳转,那么 如果我们在页面跳转的时候需要传递参数 ,该如何去做呢?

这里以页面1跳转页面2为例,假设页面1跳转到页面2时需要传递一个name参数和age参数,该如何去做呢?

传递参数

必传参数

首先,我们定义一个参数配置文件,代码如下所示:

object?ParamsConfig?{

????/**
?????*?参数-name
?????*/
????const?val?PARAMS_NAME?=?"name"

????/**
?????*?参数-age
?????*/
????const?val?PARAMS_AGE?=?"age"

}

修改NavHost的配置,代码如下所示:

NavHost(navController?=?navController,?startDestination?=?RouteConfig.ROUTE_PAGEONE)?{

????composable(RouteConfig.ROUTE_PAGEONE)?{
????????PageOne(navController)
????}

????composable(
????????"${RouteConfig.ROUTE_PAGETWO}/{${ParamsConfig.PARAMS_NAME}}/{${ParamsConfig.PARAMS_AGE}}",
????????arguments?=?listOf(
????????????navArgument("$ParamsConfig.PARAMS_NAME")?{},
????????????navArgument("$ParamsConfig.PARAMS_AGE")?{?type?=?NavType.IntType?}
????????)
????)?{
????????PageTwo(navController)
????}
}

这里,直接将传递的参数使用"/"拼写在路由地址后面添加占位符即可,默认情况下,所有的参数都会被解析成字符串,所以我们可以使用arguments来为参数指定type类型。当然,因为这里我们只需要将年龄字段指定为整形,所以 navArgument("$ParamsConfig.PARAMS_NAME") {}也可以不写,这里知道就行啦~

那么PageTwo页面该如何接收参数呢?

可以通过composable函数中提供的NavBackStackEntry来获取,并将获取的结果传递给PageTwo页面即可,修改后的代码如下所示:

?NavHost(navController?=?navController,?startDestination?=?RouteConfig.ROUTE_PAGEONE)?{

????????composable(RouteConfig.ROUTE_PAGEONE)?{
????????????PageOne(navController)
????????}

????????composable(
????????????"${RouteConfig.ROUTE_PAGETWO}/{${ParamsConfig.PARAMS_NAME}}/{${ParamsConfig.PARAMS_AGE}}",
????????????arguments?=?listOf(
????????????????navArgument("$ParamsConfig.PARAMS_AGE")?{?type?=?NavType.IntType?}
????????????)
????????)?{
????????????val?argument?=?requireNotNull(it.arguments)
????????????val?name?=?argument.getString(ParamsConfig.PARAMS_NAME)
????????????val?age?=?argument.getInt(ParamsConfig.PARAMS_AGE)
????????????PageTwo(name,age,navController)
????????}
????}

在PageTwo页面接受传递的参数,并添加一个Text用于显示,修改后的PageTwo的主要代码如下所示:

{
????????Text(text?=?"这是页面2")
????????Spacer(modifier?=?Modifier.height(20.dp))
????????Text(text?=?"我是$name,我今年$age?岁了")
????????Spacer(modifier?=?Modifier.height(20.dp))
????????Button(onClick?=?{
????????????//点击返回页面1
????????????navController.popBackStack()
????????})?{
????????????Text(
????????????????text?=?"返回页面1",
????????????????modifier?=?Modifier.fillMaxWidth(),
????????????????textAlign?=?TextAlign.Center
????????????)
????????}
????}

最后,在页面1的监听事件中使用占位符传参即可,代码如下所示:

{
????Text(text?=?"这是页面1")
????Spacer(modifier?=?Modifier.height(20.dp))
????Button(onClick?=?{
????????//点击跳转到页面2
???????navController.navigate("${RouteConfig.ROUTE_PAGETWO}/黄林晴/26")
????})?{
????????Text(
????????????text?=?"跳转页面2",
????????????modifier?=?Modifier.fillMaxWidth(),
????????????textAlign?=?TextAlign.Center
????????)
????}
}

运行程序,点击跳转页面1按钮,效果如下图所示:

?如此一来就实现了从页面1到页面2的传参,如果我们在页面1的点击事件中少传一个参数,会怎么样呢?

navController.navigate("${RouteConfig.ROUTE_PAGETWO}/黄林晴")

不用想了,会崩溃!!所以占位符的方式相当于必传参数,如果不传的话则会抛出异常,那么,如果我们想将参数设置为可选参数应该怎么样做呢?

可选参数

可选参数类似于get请求的添加方式 ?name = name,现在我们将年龄修改为一个可选参数,来看看如何修改。

首先,我们修改NavHost代码如下所示:

composable(RouteConfig.ROUTE_PAGEONE)?{
????????????PageOne(navController)
????????}

????????composable(
????????????"${RouteConfig.ROUTE_PAGETWO}/{${ParamsConfig.PARAMS_NAME}}"?+
????????????????????"?${ParamsConfig.PARAMS_AGE}={${ParamsConfig.PARAMS_AGE}}",
????????????arguments?=?listOf(
????????????????navArgument(ParamsConfig.PARAMS_NAME)?{},
????????????????navArgument(ParamsConfig.PARAMS_AGE)?{
????????????????????defaultValue?=?30
????????????????????type?=?NavType.IntType
????????????????}
????????????)
????????)?{
????????????val?argument?=?requireNotNull(it.arguments)
????????????val?name?=?argument.getString(ParamsConfig.PARAMS_NAME)
????????????val?age?=?argument.getInt(ParamsConfig.PARAMS_AGE)
????????????PageTwo(name,?age,?navController)
????????}

当前的路由地址就是“?pageTwo/{name}?age={age}”,由于可选参数必须要设置一个默认值,这里设置年龄的默认值为30,现在 在页面1的点击事件中不再传递年龄参数

navController.navigate("${RouteConfig.ROUTE_PAGETWO}/黄林晴")

再次运行程序,点击跳转页面2 按钮,运行结果如下图所示。

由图可知,我们已经成功的将年龄设置为可选参数。

总结

除此之外,Navigation? 在Compose中还支持深层链接等,关于Compose的更多用法,欢迎持续关注我~?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:02:21  更:2022-03-21 21:04:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 18:44:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码