Jetpack - Navigation: 一个全面的安卓开发指南

在这里插入图片描述

引言

导航是任何安卓应用程序中至关重要的部分。无缝地在不同的屏幕之间移动并传递数据,对于流畅的用户体验来说至关重要。在这篇博客中,我们将深入探讨Jetpack的Navigation组件,这个强大的框架旨在简化安卓应用中的导航。我们将涵盖从设置和配置到高级使用场景的所有内容。

什么是Jetpack Navigation?

Jetpack Navigation是Android Jetpack的一部分,Jetpack是一个库套件,帮助开发者遵循最佳实践,减少样板代码,并在不同版本的安卓之间编写一致的代码。Navigation组件帮助管理导航,从简单的按钮点击到更复杂的模式,如导航抽屉和底部导航。

设置Jetpack Navigation

在深入使用之前,让我们先在你的项目中设置Navigation组件。

步骤1:添加依赖项

首先,在你的build.gradle文件中添加必要的依赖项。

dependencies {def nav_version = "2.7.7"// Java语言实现implementation "androidx.navigation:navigation-fragment:$nav_version"implementation "androidx.navigation:navigation-ui:$nav_version"// Kotlinimplementation "androidx.navigation:navigation-fragment-ktx:$nav_version"implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}

步骤2:创建导航图

导航图是一个XML资源,集中定义了所有与导航相关的信息。在res/navigation目录中创建一个新的XML文件。

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/homeFragment"><fragment android:id="@+id/homeFragment" android:name="com.example.app.HomeFragment"android:label="Home" tools:layout="@layout/fragment_home" /><fragment android:id="@+id/detailsFragment" android:name="com.example.app.DetailsFragment"android:label="Details" tools:layout="@layout/fragment_details"><argument android:name="itemId" app:argType="integer" /></fragment></navigation>

在目的地之间导航

设置好导航图后,让我们来探索如何在不同的目的地之间进行导航。

基本导航

要从HomeFragment导航到DetailsFragment,可以使用NavController。这可以通过在HomeFragment
中的一个简单按钮点击来完成。

class HomeFragment : Fragment(R.layout.fragment_home) {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)val navController = findNavController()view.findViewById<Button>(R.id.navigateToDetailsButton).setOnClickListener {val action = HomeFragmentDirections.actionHomeFragmentToDetailsFragment(itemId = 1)navController.navigate(action)}}
}

传递数据

数据可以通过Safe Args在目的地之间传递。在上面的例子中,我们将itemId传递给了DetailsFragment

DetailsFragment中,按照以下方法获取参数:

class DetailsFragment : Fragment(R.layout.fragment_details) {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)val args: DetailsFragmentArgs by navArgs()val itemId = args.itemId// 使用itemId}
}

处理上和返回操作

Navigation组件自动处理上和返回操作。当使用NavController时,返回操作由Navigation UI库管理。

在Activity中设置

在你的MainActivity中,你需要设置NavController并配置ActionBar。

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val navController = findNavController(R.id.nav_host_fragment)setupActionBarWithNavController(navController)}override fun onSupportNavigateUp(): Boolean {val navController = findNavController(R.id.nav_host_fragment)return navController.navigateUp() || super.onSupportNavigateUp()}
}

高级导航模式

底部导航

Jetpack Navigation轻松支持底部导航。在res/menu中定义菜单项,并设置NavHostFragment以使用底部导航。


<menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/homeFragment" android:icon="@drawable/ic_home" android:title="Home" /><item android:id="@+id/detailsFragment" android:icon="@drawable/ic_details"android:title="Details" />
</menu>
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val navController = findNavController(R.id.nav_host_fragment)val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)bottomNavigationView.setupWithNavController(navController)}
}

侧边导航抽屉

与底部导航类似,侧边导航抽屉也可以无缝集成。定义抽屉项并设置NavHostFragment


<menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/homeFragment" android:icon="@drawable/ic_home" android:title="Home" /><item android:id="@+id/detailsFragment" android:icon="@drawable/ic_details"android:title="Details" />
</menu>
class MainActivity : AppCompatActivity() {private lateinit var drawerLayout: DrawerLayoutoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)drawerLayout = findViewById(R.id.drawer_layout)val navController = findNavController(R.id.nav_host_fragment)val navView: NavigationView = findViewById(R.id.nav_view)navView.setupWithNavController(navController)setupActionBarWithNavController(navController, drawerLayout)}override fun onSupportNavigateUp(): Boolean {val navController = findNavController(R.id.nav_host_fragment)return NavigationUI.navigateUp(navController, drawerLayout) || super.onSupportNavigateUp()}
}

动态添加Fragment

有时候,你可能需要在运行时动态添加Fragment。Jetpack Navigation也支持这种场景。

  1. 创建一个新的Fragment,例如DynamicFragment
class DynamicFragment : Fragment(R.layout.fragment_dynamic) {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)// Fragment逻辑}
}
  1. 在导航图中添加一个dynamicFragment

<fragment android:id="@+id/dynamicFragment" android:name="com.example.app.DynamicFragment"android:label="Dynamic" tools:layout="@layout/fragment_dynamic" />
  1. 在你的代码中动态添加Fragment。
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val navController = findNavController(R.id.nav_host_fragment)val fragment = DynamicFragment()supportFragmentManager.beginTransaction().replace(R.id.nav_host_fragment, fragment).addToBackStack(null).commit()}
}

复杂导航示例:导航图中嵌套导航图

在大型应用中,你可能会遇到需要嵌套导航图的情况。嵌套导航图可以帮助你组织和管理复杂的导航层次结构。

主导航图

在主导航图中定义一个包含子导航图的<include>元素。

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/mainFragment"><fragment android:id="@+id/mainFragment" android:name="com.example.app.MainFragment"android:label="Main" tools:layout="@layout/fragment_main" /><include app:graph="@navigation/nested_nav_graph" /></navigation>

嵌套导航图

创建一个新的导航图文件,例如nested_nav_graph.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/nestedFragmentA"><fragment android:id="@+id/nestedFragmentA" android:name="com.example.app.NestedFragmentA"android:label="Nested A" tools:layout="@layout/fragment_nested_a" /><fragment android:id="@+id/nestedFragmentB" android:name="com.example.app.NestedFragmentB"android:label="Nested B" tools:layout="@layout/fragment_nested_b" /></navigation>

这样,你可以在主导航图中导航到子导航图中的目的地。

class MainFragment : Fragment(R.layout.fragment_main) {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)val navController = findNavController()view.findViewById<Button>(R.id.navigateToNestedButton).setOnClickListener {navController.navigate(R.id.nestedFragmentA)}}
}

结论

Jetpack Navigation简化了安卓导航中的复杂性,提供了一个强大的框架来管理各种导航场景。从基本的Fragment事务到更复杂的导航模式如底部导航和侧边导航抽屉,Navigation组件提高了开发过程的可管理性和效率。

Best regards!

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

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

相关文章

ABAP开发:动态Open SQL编程案例介绍

动态Open SQL是Open SQL的扩展。它不是要求整个SQL语句都是动态指定的。通过熟悉的静态ABAP编码表达静态已知的部分&#xff0c;动态元素的部分通过动态标记指定。动态片段不明确包含在ABAP源代码中&#xff0c;而是源代码包含一个ABAP变量&#xff0c;用括号括起来作为占位符。…

CSS的媒体查询:响应式布局的利器

关于CSS的媒体查询 CSS媒体查询是CSS层叠样式表(Cascading Style Sheets)中的一个核心功能&#xff0c;它使得开发者能够根据不同的设备特性和环境条件来应用不同的样式规则。这是实现响应式网页设计的关键技术&#xff0c;确保网站或应用能够在多种设备上&#xff0c;包括桌面…

YOLOV8图像分割预测后输出mask图

训练一个yolov8后&#xff0c;用官方的预测脚本一般是&#xff1a; results model.predict(img_path, saveTrue, save_diroutput_folder) 运行此代码会直接在run里面生成一个文件夹&#xff0c;保存预测图像。如果要获取分割后的mask点&#xff0c;或mask的轮廓点&#xff0…

nacos使用shared-configs设置多个配置文件后,配置中修改无法动态更新 解决办法

问题描述 今天使用nacos去做配置分离&#xff0c;启动成功了&#xff0c;配置也读取了&#xff0c;但是当我修改nacos中的配置时&#xff0c;发现数据无法动态更新 下面是测试接口的调用 可以看到我修改配置后&#xff0c;接口返回的参数依然是老参数 问题排查 首先检查了…

C++实现一个简单的Qt信号槽机制

昨天写这个文章《深入探讨C的高级反射机制&#xff08;2&#xff09;&#xff1a;写个能用的反射库》的时候就在想&#xff0c;是不是也能在这套反射逻辑的基础上&#xff0c;实现一个类似Qt的信号槽机制&#xff1f; Qt信号槽机制简介 所谓的Qt的信号槽&#xff08;Signals …

基于VUE3+VITE+SpringBoot+Nginx部署项目之跨域配置等问题

前言&#xff1a;遇到问题&#xff0c;解决问题。 第一部分&#xff1a;VUE 配置 1、vite.config.js 文件 server: {proxy: {/api: {target: env.VITE_BASE_URL,changeOrigin: true,secure: false,rewrite: path > path.replace(/^\/api/, )}}}, 2、.env 文件 VITE_BAS…

springcloud-config 客户端启用服务发现client的情况下使用metadata中的username和password

为了让spring admin 能正确获取到 spring config的actuator的信息&#xff0c;在eureka的metadata中添加了metadata.user.user metadata.user.password eureka.instance.metadata-map.user.name${spring.security.user.name} eureka.instance.metadata-map.user.password${spr…

气象相关图表制作-字体图标、图片、折线的堆叠

开发工作中有个需要展示气温&#xff08;折线&#xff09;、天气&#xff08;图片&#xff09;、风羽&#xff08;字体图标&#xff09;的图表展示需求&#xff0c;之前用过highcharts的关于类似的chart&#xff0c;里面的风雨用的是自带的图片&#xff0c;但是现在要求风羽需要…

Windows环境本地部署开源在线演示文稿应用PPTist并实现远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Linux双网卡默认路由的metric设置不正确,导致SSH连接失败问题定位

测试环境 VMware虚拟机 RockyLinux 9 x86_64 双网卡&#xff1a;eth0(访问外网): 10.206.216.92/24; eth1(访问内网) 192.168.1.4/24 问题描述 虚拟机重启后&#xff0c;SSH连接失败&#xff0c;提示"Connection time out"&#xff0c;重启之前SSH连接还是正常的…

基于Spring Boot医护人员排班系统

设计技术&#xff1a; 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatisvue 工具&#xff1a;IDEA、Maven、Navicat 主要功能&#xff1a; 医护类型管理 医护人员排班系统的系统管理员可以对医护类型添加修改删除以及查询操作。具体界面…

SS8870T-3.6A 扫地机和滚刷电机的大电流电机驱动

扫地机器人已经成为现代家庭清洁的必备工具&#xff0c;而其中的关键部件——电机&#xff0c;对于其性能和用户体验起着至关重要的作用。为了确保扫地机器人的高效清洁和稳定运行&#xff0c;至少需要使用7个直流电机&#xff0c;包括行走轮、滚轮、边刷和吸尘等功能的驱动。 …

Python接口测试课程,每天学会一个Python小知识!

第一天: Python基础 Python简介、环境搭建及包管理 Python简介&#xff1a; 特点&#xff1a;Python是一门动态、解释型、强类型语言 动态&#xff1a;在运行期间才做数据检查&#xff08;不用提前声明变量&#xff09;- 静态语音(C/Java)&#xff1a;编译时检查数据类型&…

根据指定日期自定义el-date-picker日期选择器样式

需求 功能需要在DatePicker日期选择器中&#xff0c;对有数据的日期下方添加小圆点提示样式&#xff0c;后台会返回按年份查询的日期数据 dayjs插件 dayjs中文网&#xff1a;https://dayjs.fenxianglu.cn/ npm install dayjs实现点 配置picker-options对象中的cellClassName属性…

django 逆向生成对应数据库表的models模型类 —— python

一&#xff0c;在setting.py中配置好连接数据库的参数 在setting中的DATABASESZ中配置默认参数&#xff0c;并在INSTALLED_APPS中导入模块名。 DATABASES {default:{ENGINE: django.db.backends.mysql, # 数据库引擎NAME: jljupcs, # 数据库名称HOST: 127.0.0.1, # 数据库…

检索增强生成RAG系列1--RAG的实现

大模型出现涌现能力之后&#xff0c;针对大模型的应用也如雨后春笋般。但是&#xff0c;在大模型真正落地之前&#xff0c;其实还需要做好最后一公里&#xff0c;而这个最后一公里&#xff0c;其中不同应用有着不同的方法。其中prompt、微调和RAG都是其中方法之一。本系列就是针…

简单的同步压缩变换脊线检测(PythonMATLAB)

由于 Heisenberg 测不准原理&#xff0c;线性时频变换方法无法同时在时间和频率方向达到最佳的时频分布&#xff0c;窗函数和小波函数的选择也降低了各方法的自适应性。同样&#xff0c;二次型变换方法难以在去除交叉干扰项的同时保证较高的能量集中度。为了解决该问题&#xf…

MySQL的安装与配置

MySQL提供安装包和压缩包两种安装方式&#xff0c;安装包是以.msi作为后缀名的二进制分发文件&#xff0c;压缩包是以.zip为后缀的压缩文件。安装包的安装只要双击安装文件&#xff0c;然后按照提示一步步安装就可以了&#xff0c;属于“傻瓜”式安装&#xff1b;压缩包的安装需…

基于SpringBoot校园一卡通系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; Java精品实战案例《600套》 2023-2025年最值得选择的Java毕业设计选题大全&#xff1…

World of Warcraft [CLASSIC] Level 70 Riding Skill

World of Warcraft http://account.battlenet.com.cn-CSDN博客 World of Warcraft [CLASSIC] Level 70 Riding Skill 魔兽世界【怀旧】70级骑术 部落如何学习70级骑术&#xff0c;如何区影月谷&#xff0c;影月村&#xff0c;怀旧一下 荆棘谷 暮色森林 逆风小径 悲伤沼泽 诅…