Compose | UI组件(十三) | Navigation - 页面导航

文章目录

    • 前言
    • Navaigation 的核心概念和组件的更详细说明
    • 真实案例带你一步一步了解 Navaigation
      • 第一步,新建多个页面
      • 第二步,新建一个Activity
      • 第三步,新建一个Screen类,用于统一管理导航的常量
      • 第四步,新建一个Graph 统一管理方法
      • 第四步,通过 NavGraphBuilder 的扩展函数 navigation 分组
      • 第五步,通过 NavGraphBuilder 的扩展函数 分组
      • 第六步,跳转的例子
        • Main - > Login (各模块间跳转)
        • Login - > Signup (单独模块内各页面间跳转)
        • SignUp -> Login (返回上一级)
        • Login - > Home (返回不同模块的第一个页面)
        • Login - > Home -> Detail (返回不同模块上一级,再跳转到不同模块下级页面)
        • SignUp -> Home (最顶级页面 跳转到 首页,并且设置为 首页 为 栈顶模式 )
    • 总结


前言

关于大前端,不管是Android还是IOS,Web端都会涉及到页面之间的跳转或传值

今天我们要讲的就是Compose中及其重要的组件 Navigation (页面导航)


Navaigation 的核心概念和组件的更详细说明

Compose Navigation 是一个用于 Jetpack Compose 的导航组件,它提供了简单而强大的 API 来处理页面跳转和用户界面交互。以下是 Compose Navigation 的核心概念和组件的更详细说明:

  1. NavController
    • 定义:NavController 是导航组件的中心 API,负责控制页面导航的流程。
    • 作用:它维护了 Navigation 内部关于页面的堆栈、状态信息、导航图。
    • 创建:通过 rememberNavController() 方法创建 NavController 实例。
  2. NavHost
    • 定义:NavHost 是一个 Composable 函数,用于承载导航的页面,同时也是承载导航页面的容器。
    • 参数:NavHost 需要两个必传参数,一个是 NavController,一个是起始路由地址。
    • 作用:内部持有 NavController,在页面切换时渲染 UI。通过 composable() 函数构建路线(节点)。
  3. Screen
    • 定义:Screen 是表示一个单独的、完整的 UI 屏幕的组件。可以将其视为一个页面,包含了一个完整的 UI 布局。
    • 创建:通过 Screen 组件创建 Screen 实例。
  4. Route
    • 定义:Route 是导航路径的抽象表示,用于定义页面之间的跳转关系。
    • 创建与管理:通过 NavHost 和 NavController 定义和管理多个 Route。
  5. Params
    • 定义:Params 是传递给目标 Screen 的数据。
    • 传递方式:通过 NavController 的 navigate() 方法传递 Params。在目标 Screen 中接收和使用这些参数。
  6. Backstack
    • 定义:Backstack 是保存和恢复导航状态的机制。
    • 管理方式:通过 NavController 的 backstack 属性,可以管理用户的导航历史,并执行后退操作。
  7. Transitions
    • 定义:Transitions 是用于页面切换的动画效果。
    • 提供与自定义:Compose Navigation 提供了一组默认的过渡动画,也可以自定义过渡效果,以提供流畅的用户体验。
  8. Lazy Entry
    • 定义:Lazy Entry 是一种懒加载技术,允许延迟加载一些不立即需要的页面。
    • 用途:优化性能和资源使用。
  9. Graph:
    • 定义:统一所有的Destination信息,以及可能的跳转路径
    • 用途:Navigation需要收集各节点之间的跳转关系,因此NavDestinotion需要集中在一起,统一由Graph管理
  10. NavLink:类似于 Web 中的锚点,可以用来实现页面内的跳转。

这些核心概念和组件为开发者提供了构建复杂的导航结构和用户界面交互的工具,使得在 Jetpack Compose 应用中实现高效的页面跳转和数据传递变得简单而强大。通过合理使用这些概念和组件,可以创建出具有良好用户体验的应用程序。


真实案例带你一步一步了解 Navaigation

第一步,新建多个页面

多个页面相当于传统View里面的Fragment

HomeScreen.kt

@Composable
fun HomeScreen(navController: NavController){
Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {Text(modifier = Modifier.clickable {},text  = "Home",color = MaterialTheme.colorScheme.primary,style = MaterialTheme.typography.displayLarge)Text(modifier = Modifier.padding(top = 150.dp).clickable {},text  = "Login/SinUp",color = Color.Black,style = MaterialTheme.typography.headlineMedium)}
}

LoginScreen.kt

@Composable
fun LoginScreen(navController: NavController){Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {Text(modifier = Modifier.clickable {},text  = "Login",color = Color.Magenta,style = MaterialTheme.typography.displayLarge)Text(modifier = Modifier.padding(top = 150.dp).clickable {},text  = "Go Back",color = Color.Black,style = MaterialTheme.typography.headlineMedium)}
}

SignUpScreen.kt

@Composable
fun SignUpScreen(navController: NavController){Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center) {Text(modifier = Modifier.clickable {},text  = "SingUp",color = Color.Green,style = MaterialTheme.typography.displayLarge)}
}

DetailScreen.kt

@Composable
fun DetailScreen(navController: NavController){Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center) {Text(modifier = Modifier.clickable {},text  = "Detail",color = Color.Red,style = MaterialTheme.typography.displayLarge)}
}

第二步,新建一个Activity

class NavigationActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {ComposeProjectTheme {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {SetupNavGraph(rememberNavController())}}}}
}

注:在Activity中写了一个SetupNavGraph方法,该方法就是设置导航的统一管理方法

第三步,新建一个Screen类,用于统一管理导航的常量

Screen.kt

const val AUTHENTICATION_ROUTE = "authentication"
const val ROOT_ROUTE = "root"
const val HOME_ROUTE = "home"const val HOME   = "home_screen"
const val LOGIN  = "login_screen"
const val SIGNUP = "signup_screen"
const val DETAIL = "detail_screen"sealed class Screen(val route:String){object Home:Screen(route = HOME)object Login:Screen(route = LOGIN)object Signup:Screen(route = SIGNUP)object Detail:Screen(route = DETAIL)
}

第四步,新建一个Graph 统一管理方法

NavGraph.kt

@Composable
fun SetupNavGraph(navController: NavHostController){NavHost(navController = navController, startDestination = Screen.Home.route){composable(route = Screen.Home.route){HomeScreen(navController   = navController)}composable(route = Screen.Detail.route){DetailScreen(navController = navController)}composable(route = Screen.Login.route){LoginScreen(navController  = navController)}composable(route = Screen.Signup.route){SignUpScreen(navController = navController)}}
}

注:
至此,就可以运行项目,显示主页面了。

但是细心的小伙伴,发现了没有,其实我们平时做项目,可能是多模块开发,

所以,我们现在可以把 HomeDetail 封装成一模块,把 LoginSignup 分成一个模块

第四步,通过 NavGraphBuilder 的扩展函数 navigation 分组

@Composable
fun SetupNavGraph(navController: NavHostController){NavHost(navController = navController, startDestination = HOME_ROUTE, route = ROOT_ROUTE){navigation(startDestination = Screen.Home.route,route = HOME_ROUTE){composable(route = Screen.Home.route){HomeScreen(navController   = navController)}composable(route = Screen.Detail.route){DetailScreen(navController = navController)}}navigation(startDestination = Screen.Login.route,route = AUTHENTICATION_ROUTE){composable(route = Screen.Login.route){LoginScreen(navController  = navController)}composable(route = Screen.Signup.route){SignUpScreen(navController = navController)}}}
}

注:
看上面代码,其实还可以优化,可以通过kotlin的扩展函数,来做分组

第五步,通过 NavGraphBuilder 的扩展函数 分组

HomeNavGraph.kt

fun NavGraphBuilder.homeNavGraph(navController: NavHostController){navigation(startDestination = Screen.Home.route,route = HOME_ROUTE){composable(route = Screen.Home.route){HomeScreen(navController   = navController)}composable(route = Screen.Detail.route){DetailScreen(navController = navController)}}
}

HomeNavGraph.kt

fun NavGraphBuilder.authNavGraph(navController: NavHostController){navigation(startDestination = Screen.Login.route,route = AUTHENTICATION_ROUTE){composable(route = Screen.Login.route){LoginScreen(navController  = navController)}composable(route = Screen.Signup.route){SignUpScreen(navController = navController)}}
}

NavGraph.kt

@Composable
fun SetupNavGraph(navController: NavHostController){NavHost(navController = navController, startDestination = HOME_ROUTE, route = ROOT_ROUTE){homeNavGraph(navController = navController)authNavGraph(navController = navController)}
}

注:
现在看下Graph类的代码是不是简洁很多,而且子模块的分组逻辑清晰,

上面代码有个注意的点: startDestination = HOME_ROUTE,这里指向了 navigation 扩展函数的route的值

第六步,跳转的例子

Main - > Login (各模块间跳转)

HomeScreen

@Composable
fun HomeScreen(navController: NavController){
Column(...) {Text(modifier = Modifier.clickable {navController.navigate(AUTHENTICATION_ROUTE)},...)...}
}

AuthNavGraph.kt

fun NavGraphBuilder.authNavGraph(navController: NavHostController){navigation(startDestination = Screen.Login.route,route = AUTHENTICATION_ROUTE){composable(route = Screen.Login.route){LoginScreen(navController  = navController)}composable(route = Screen.Signup.route){SignUpScreen(navController = navController)}}
}

注:navController.navigate 指向 navigationroute 的值,startDestination的值是 Screen.Login.route,因此跳转到了登录页面

Login - > Signup (单独模块内各页面间跳转)

LoginScreen.kt

@Composable
fun LoginScreen(navController: NavController){Column(...) {Text(modifier = Modifier.clickable {navController.navigate(route = Screen.Signup.route)},...)...}
}
SignUp -> Login (返回上一级)

SignUpScreen.kt

@Composable
fun SignUpScreen(navController: NavController){Box(...) {Text(modifier = Modifier.clickable {navController.popBackStack()},...)}
}
Login - > Home (返回不同模块的第一个页面)

LoginScreen

@Composable
fun LoginScreen(navController: NavController){Column(...) {Text(...)Text(modifier = Modifier.padding(top = 150.dp).clickable {navController.navigate(HOME_ROUTE){popUpTo(HOME_ROUTE)}},...)}
}

注:popUpTo 清除当前栈顶到节点 HOME_ROUTE 之间所有节点(不包含 Screen.Home.route

Login - > Home -> Detail (返回不同模块上一级,再跳转到不同模块下级页面)
@Composable
fun LoginScreen(navController: NavController){Column(...) {Text(...)Text(...)Text(modifier = Modifier.padding(top = 30.dp).clickable {navController.popBackStack()navController.navigate(Screen.Detail.route)},...)}
}

注:
navController.popBackStack() 返回不同模块上一级,navController.navigate(Screen.Detail.route) 跳转到不同模块下级页面

SignUp -> Home (最顶级页面 跳转到 首页,并且设置为 首页 为 栈顶模式 )
@Composable
fun SignUpScreen(navController: NavController){Column(...) {Text(...)Text(modifier = Modifier.clickable {navController.navigate(HOME_ROUTE){popUpTo(HOME_ROUTE){ inclusive = true}}},...)Text(modifier = Modifier.clickable {navController.navigate(HOME_ROUTE){launchSingleToppopUpTo(HOME_ROUTE)}},...)}
}

注:
至此,页面之间跳转的各种情况都讲到了,如有发现其他问题和补充,欢迎反馈和评论区留言

后续关于页面之间的传参,单独写篇文章讲解,后续再会…


总结

  1. Compose Navigation 是一个用于 Jetpack Compose 的导航组件,它提供了简单而强大的 API 来处理页面跳转用户界面交互
  2. NavController 是导航组件的中心 API,负责 控制页面导航的流程,通过 rememberNavController() 创建
  3. NavHost 是一个 Composable 函数,用于 承载导航的页面,同时也是 承载导航页面的容器
  4. 通过 navController.navigate(route路径) 导航页面
  5. 通过 navController.popBackStack() 返回上一页面
  6. 通过 popUpTo 清除 当前栈顶当前节点 之间的 所有节点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/662368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玻璃钢制品三维扫描机械抄数全尺寸检测服务对比测量检查重合度

玻璃钢制品是一种广泛应用于建筑、汽车、航空航天等领域的复合材料。其制作过程中,需要确保每个环节的精确度,以确保最终产品的质量和性能。为了实现这一目标,三维扫描仪在玻璃钢制品的生产过程中发挥着至关重要的作用。 CASAIM中科广电高精度…

2024美赛数学建模A题思路分析 - 资源可用性和性别比例

1 赛题 问题A:资源可用性和性别比例 虽然一些动物物种存在于通常的雄性或雌性性别之外,但大多数物种实质上是雄性或雌性。虽然许多物种在出生时的性别比例为1:1,但其他物种的性别比例并不均匀。这被称为适应性性别比例的变化。例…

BC1.2 SDP/CDP/DCP介绍

参考:文章链接 Microchip Lightning Support 问题 Q1.) 在Microchip产品的数据表中提到了电池充电技术,但以下术语是什么意思: BC1.2? SDP? CDP? DCP? “SE1”? Q2.) 如何配置Microchip Hub以启用这些功能? Q3.) 如何在我的硬件上物…

基于QPSO-LSTM的短期风电负荷MATLAB预测程序

微❤关注“电气仔推送”获得资料(专享优惠) 参考文献 基于QPSO-LSTM的短期风电负荷预测模型——谭才兴(完全复现) 程序简介 传统的LSTM神经网络超参数和拓扑结构通常是基于经验和试验确定,但这种方法容易受到人为因…

学习嵌入式第十五天之结构体

用变量a给出下面的定义 a) 一个整型数(An integer) //int a;b) 一个指向整型数的指针(A pointer to an integer) //int *a;c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a poin…

在Vue 3中,如何理解使用CSS变量(也被称为自定义属性)来动态地设置和更新组件的样式

在Vue 3中&#xff0c;你可以使用CSS变量&#xff08;也被称为自定义属性&#xff09;来动态地设置和更新组件的样式。Vue 3提供了<style vars>块&#xff0c;使你可以在单个组件中定义CSS变量。 以下是一个示例&#xff0c;展示如何在Vue 3中使用CSS变量&#xff1a; …

Leetcode—2950. 可整除子串的数量【中等】Plus(前缀和题型)

2024每日刷题&#xff08;一零八&#xff09; Leetcode—2950. 可整除子串的数量 算法思想 让 f ( c ) d , 其中 d 1 , 2 , . . . , 9 f(c) d, 其中d 1, 2, ..., 9 f(c)d,其中d1,2,...,9. // f(c1) f(c2) ... f(ck) / k avg // > f(c1) f(c2) ... f(ck) - …

[opencvsharp]C#基于Fast算法实现角点检测

角点检测算法有很多&#xff0c;比如Harris角点检测、Shi-Tomas算法、sift算法、SURF算法、ORB算法、BRIEF算法、Fast算法等&#xff0c;今天我们使用C#的opencvsharp库实现Fast角点检测 【算法介绍】 fast算法 Fast(全称Features from accelerated segment test)是一种用于角…

【JavaScript】手写 Promise(核心功能)

1. 构造函数 定义类添加构造函数&#xff0c;接收 func 函数参数定义 resolve&#xff0c;reject执行回调函数&#xff0c;传入自定义的 resolve 和 reject class MyPromise {constructor(func) {const resolve (result) > {console.log(run, result)}const reject (res…

Docker 集群配置

1、配置 MySQL MySQL 简单安装 docker安装完MySQL并run出容器后&#xff0c;建议请先修改完字符集编码后再新建mysql库-表-插数据 docker run -d -p 2222:3306 --privilegedtrue -e MYSQL_ROOT_PASSWORD123456 \ -v /opt/mysql/log:/var/log/mysql \ -v /opt/mysql/data:/va…

微服务gptapi开发记录(一)

最近跟着网上在弄gpt微信公众号 最近主要做了几件事情 1.深入学习了springboot的原理和技术框架。 2.学习了http访问的相关 3.实现了公众号跟本地springboot的对接 4.实现了本地调用gpt的gpt3.5-api成功。 第一&#xff1a;springboot的原理和技术框架。 springboot是微…

Spring:JDBCTemplate 的源码分析

一&#xff1a;JdbcTemplate的简介 JdbcTemplate 是 Spring Template设置模式中的一员。类似的还有 TransactionTemplate、 MongoTemplate 等。通过 JdbcTemplate 我们可以使得 Spring 访问数据库的过程简单化。 二&#xff1a;执行SQL语句的方法 1&#xff1a;在JdbcTempla…

前端性能优化:Vue项目打包后app.xxx.js 和 chunk-vendors.xxx.js 文件太大,导致页面加载时间太长

问题场景&#xff0c;如下图&#xff0c;环境上的 app.js 和chunk-vendors.js 两个文件大小&#xff0c;高达3.4M 和 2M &#xff0c;加载所耗费的时间也很长。 下面说一下如何解决&#xff1a; 1、首先需要安装插件 compression-webpack-plugin&#xff0c;我这里用的是6.1.1…

情人节送什么礼给男朋友合适?适合送男友的礼物合集

情人节即将来临&#xff0c;作为贴心的女友&#xff0c;你是否已经开始为男友精心挑选礼物了呢&#xff1f;为了让这个特殊的日子充满温馨与甜蜜&#xff0c;选择一份既实用又充满心意的礼物是至关重要的&#xff0c;下面为大家推荐一些适合在情人节送给男友的好物&#xff0c;…

探索自然语言处理在改善搜索引擎、语音助手和机器翻译中的应用

文章目录 每日一句正能量前言文本分析语音识别机器翻译语义分析自然语言生成情感分析后记 每日一句正能量 努力学习&#xff0c;勤奋工作&#xff0c;让青春更加光彩。 前言 自然语言处理&#xff08;NLP&#xff09;是人工智能领域中与人类语言相关的重要研究方向&#xff0c…

搭建gitlab仓库

yum安装gitlab仓库 搭建gitlab仓库 配置yum源 vim /etc/yum.repos.d/gitlab-ce.repo [gitlab-ce] namegitlab-ce baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7 gpgcheck0 Repo_gpgcheck0 Enabled1 Gpgkeyhttps://packages.gitlab.com/gpg.keysudo yum ins…

腾讯主导制定全球首个车载小程序国际标准,助力车载应用生态发展

2024年1月&#xff0c;国际电信联盟标准部门&#xff08;ITU-T&#xff09;正式发布了由腾讯主导制定的《F.749.8 In-vehicle multimedia applets: Framework and functional requirements》(车载多媒体小程序框架和技术需求)国际标准。 这是全球首个由中国企业主导制定的车载小…

LNMP环境搭建动态网站

一、环境准备 服务器&#xff1a;openEuler 22.03 Linux IPV4 &#xff1a;192.168.110.144/24 网页服务器&#xff1a;Nginx1.21.0 数据库&#xff1a;MySQL 8.0.36 PHP&#xff1a;8.0.30 1.安装软件 [rootnode3 ~]# yum install php-mysqlnd php php-gd php-fpm php-xml -y…

在ESXi中部署时出现the host does not support intel vt-x

在VCenter中新建了一台ESXi用于部署VCSA进行实验 在部署VCSA的第二阶段&#xff0c;出现the host does not support intel vt-x&#xff0c;部署失败。 解决办法&#xff1a;点进ESXi虚拟机的设置界面&#xff08;要先关机&#xff09;&#xff0c;将硬件虚拟化打开&#xff0c…

Socket.D 协议的开发缘由

为什么搞个新协议&#xff1f; 2021年时&#xff0c;想为 Solon 生态 提供一种 MVC 体验的 Socket 和 WebSocket 开发方式。这个想法&#xff0c;要求消息“能路由”、“有元信息”、“可建立关联性”。于是就开发了 Socket.D 早期版本&#xff08;算是草案版&#xff09;。经…