Jetpack学习之Navigation

2023-10-29

Jetpack提供了一个名为Navigation的组件,用来管理页面(Actvity和Fragment,以Fragment为主)和App bar。

Navigation的优势:
  • 可视化的页面导航图,便于理清页面间的关系
  • 通过destination和action完成页面间的导航
  • 方便添加页面切换动画
  • 页面间类型安全的参数传递
  • 通过NavigationUI类,对菜单、底部导航、抽屉菜单导航进行统一的管理
  • 支持深层链接DeepLink
Navigation的主要元素
  1. Navigation Graph。一种新型的XML资源文件,其中包含应用程序所有的页面,以及页面间的关系。
  2. NavHostFragment。这是一个特殊的Fragment,是其他Fragment的“容器”,Navigation Graph中的Fragment正是通过NavHostFragment进行展示的。
  3. NavController。这个是一个Java/kotlin对象,用于在代码中完成Navigation Graph中具体的页面切换工作。
使用方法
  1. 添加依赖
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
  1. 创建Navigation Graph
    在res文件中新建一个Navigation Graph文件,将File name设置为“nav_graph”,Resource Type设置为“Navigation”。
  2. 添加NavHostFragment
    在Activity的布局文件中添加NavHostFragment
<fragment
        android:id="@+id/nav_host_fragment_content_main"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
android:name="androidx.navigation.fragment.NavHostFragment"
表明这是一个特殊的Fragment
app:defaultNavHost="true"
该Fragment会自动处理系统返回键
app:navGraph="@navigation/nav_graph"
设置该Fragment对应的导航图
  1. 创建destination
<?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"
    android:id="@+id/nav_graph"
    app:startDestination="@id/FirstFragment">

    <fragment
        android:id="@+id/FirstFragment"
        android:name="com.example.myapplication.FirstFragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first">

        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment" />
    </fragment>
    <fragment
        android:id="@+id/SecondFragment"
        android:name="com.example.myapplication.SecondFragment"
        android:label="@string/second_fragment_label"
        tools:layout="@layout/fragment_second">

        <action
            android:id="@+id/action_SecondFragment_to_FirstFragment"
            app:destination="@id/FirstFragment" />
    </fragment>
</navigation>
app:startDestination="@id/FirstFragment"
表明FirstFragment为起始Fragment,即NavHostFragment容器首先展示的Fragment
app:destination="@id/SecondFragment"
表示action动作的目的地是SecondFragment
  1. 使用NavController完成导航
    添加FirstFragment的布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <TextView
        android:id="@+id/textview_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_first_fragment"
        app:layout_constraintBottom_toTopOf="@id/button_first"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/next"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textview_first" />
</androidx.constraintlayout.widget.ConstraintLayout>

在Fragment中添加Button点击的监听

        binding.buttonFirst.setOnClickListener {
            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
        }
  1. 添加页面切换动画效果
    在res/anim文件中添加动画文件slide_in_left.xml,slide_in_right.xml,slide_out_left.xml,slide_out_right.xml
    然后修改nav_graph文件的action
        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
使用safe args插件传递参数
  1. 在Project的build.gradle中添加依赖
dependencies {
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.2"
    }

在app的build.gradle中添加依赖

plugins {
    id 'androidx.navigation.safeargs'
}
  1. 在nav_graph中添加<argument>标签
<fragment
        android:id="@+id/FirstFragment"
        android:name="com.example.myapplication.FirstFragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first">

        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />

        <argument
            android:name="user_name"
            app:argType="string"
            android:defaultValue="unknown"/>
        <argument
            android:name="age"
            app:argType="integer"
            android:defaultValue="0"/>
    </fragment>
  1. 在FirstFragment中传递参数
val bundle = FirstFragmentArgs.Builder().setUserName("Name").setAge(20).build().toBundle()
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment, bundle)
  1. 在SecondFragment中接收参数
        arguments?.let {
            val userName = FirstFragmentArgs.fromBundle(it).userName
            val age = FirstFragmentArgs.fromBundle(it).age
            binding.textviewSecond.text = "$userName $age"
        }
NavigationUI的使用方法

Navigation和App bar都需要处理页面切换事件,为了方便管理,Jetpack引入了NavigationUI组件,使App bar中的按钮和菜单能够与Navigation Graph中的页面关联起来。

  1. 在res/menu中创建menu_main.xml文件,为ActionBar添加菜单。注意<itme/>的id与导航图中fragment的id是一致的。
<menu 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"
    tools:context="com.example.myapplication.MainActivity">
    <item
        android:id="@+id/FirstFragment"
        android:title="@string/first_fragment_label"
        app:showAsAction="never" />

    <item
        android:id="@+id/SecondFragment"
        android:title="@string/second_fragment_label"
        app:showAsAction="never" />
</menu>
  1. 在Activity中实例化菜单。
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }
  1. 绑定Navigation和ActionBar
private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding
    private lateinit var navController: NavController

    private val myLifecycleObserver = MyLifecycleObserver(MainActivity::class.java.simpleName)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.toolbar)

        navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)

    }
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return NavigationUI.onNavDestinationSelected(item, navController) || super.onOptionsItemSelected(item)
    }

    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp(appBarConfiguration)
                || super.onSupportNavigateUp()
    }

AppBarConfiguration用于App bar的配置,NavController用于页面的导航和切换,通过setupActionBarWithNavController方法将二者绑定起来。
同时Jetpack提供了对页面切换事件的监听。

navController.addOnDestinationChangedListener { controller, destination, arguments -> TODO("Not yet implemented") }
深层链接DeepLink
PendingIntent

当应用程序接收到某个通知推送,用户在单击该通知时,能够直接跳转到展示通知内容的页面。
获取创建通知的PendingIntent

    private fun getPendingIntent(): PendingIntent {
        val bundle = Bundle()
        bundle.putString("params", "Notification Params")
        return navController.createDeepLink().setGraph(R.navigation.nav_graph)
            .setDestination(R.id.SecondFragment).setArguments(bundle).createPendingIntent()
    }
URL
  1. 在nav_graph中添加<deepLink/>标签
<fragment
        android:id="@+id/FirstFragment"
        android:name="com.example.myapplication.FirstFragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first">

        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />

        <argument
            android:name="user_name"
            app:argType="string"
            android:defaultValue="unknown"/>
        <argument
            android:name="age"
            app:argType="integer"
            android:defaultValue="0"/>

        <deepLink app:uri="www.YourAddress.com/{params}"/>
    </fragment>
  1. 在AndroidManifest中为Activity添加<nav-graph/>标签
<activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.MyApplication.NoActionBar">
            <nav-graph android:value="@navigation/nav_graph"/>
            </intent-filter>
        </activity>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jetpack学习之Navigation 的相关文章

随机推荐

  • Sqlalchemy filter与filter_by查询语法

    摘要 https www cnblogs com kaerxifa p 13391722 html 摘要2 https blog csdn net gymaisyl article details 96601798 filter与filet
  • java部署和调用智能合约

    java部署和调用智能合约 下载安装npm和solc 1 安装gcc yum install gcc gcc c 2 安装node wget https npm taobao org mirrors node v10 14 1 node v
  • java中删除文件/文件夹的3种方法

    1 通过io删除文件 通过递归逐层删除文件信息 param filePath public static void deleteFileByIO String filePath File file new File filePath Fil
  • insert oracle用法,insert into select的实际用法,insertselect

    insert into select的实际用法 insertselect INSERT INTO SELECT语句 语句形式为 Insert into Table2 field1 field2 select value1 value2 fr
  • 【Linux】进程信号

    1 理解信号 1 信号 能够识别并做出行为的一种指令 2 信号来临的时候不一定能够立即对信号做出处理 但是并不影响信号的产生 3 信号来临 gt 时间窗口 gt gt 被处理 结果是要处理的但是需要时间 4 对待信号的处理方法 1 默认2
  • vue父组件向子组件传值

    子组件
  • JAVA IO流文本文件读入方法(read方法读入数据)

    在字符流通常都使用read方法读入数据 而read方法一般都两种调用方式 首先先创建一个文件 如Hello txt 里面输入HelloWorld 第一种是使用read的空参调用 read read 从输入流中读入一个字符 若当前位置无数据则
  • 进制转换方法

    常用计算机各进制的含义和相互之间的简单转换方法 文章目录 常用计算机各进制的含义和相互之间的简单转换方法 一 理解进制含义 1 二进制 2 八进制 3 十进制 4 十六进制 二 进制之间转换 1 1二进制转十进制 1 2十进制转二进制 除法
  • java--基础--17.7--线程--内存模型与线程

    java 基础 17 7 线程 内存模型与线程 1 内存模型 1 1 主内存和工作内存之间的交互 1 2 对于 volatile 型变量的特殊规则 关键字 volatile 是 Java 虚拟机提供的最轻量级的同步机制 一个变量被定义为 v
  • 微信小程序设置背景图铺满顶部

    由于微信小程序自带顶部导航栏 导致我们设置背景图时总是无法铺满顶部 其实想要铺满顶部只需要改变一个属性即可 将navigationStyle的默认属性修改为custom 在微信小程序需要设置背景图的文件下的 json文件中设置
  • VxWorks的环境配置

    转载请标记出处 http blog csdn net zgh1988 article details 7994538 1 准备工作 1 VMWare 2 一台安装Windows XP或Window 7系统的PC机 3 Tornado 2 2
  • 进阶训练技巧提升模型性能

    在深度学习的世界中 训练技巧的重要性不言而喻 进阶训练技巧 包括损失函数 学习率 模型微调和半精度训练 更是对提升模型性能和准确率有着关键作用 下面我们将对这些技巧进行详细的探讨 一 损失函数 Loss Function 损失函数 或者叫作
  • 遍历map

    keySet是键的集合 Set里面的类型即key的类型 entrySet是 键 值 对的集合 Set里面的类型是Map Entry 1 keySet Map map new HashMap Iterator it map keySet it
  • 代码审计之JAVA代码审计洞态IAST系统以及SecExample靶场

    目录 2 JAVA系列代码审计 2 1 工具介绍 2 2 SecExample靶场安装 2 3 洞态IAST安装 2 3 洞态IAST使用 2 JAVA系列代码审计 之前我们都是采用代码审计工具对PHP代码进行审计 但是在实际的工作中对于从
  • unipush2.0教程

    解释一下名词 透传消息 无论手机app 是否在运行 打开了 还是清了后台 关闭 都可以收到消息 通知消息 只能app打开了 才能收到 1 开通unipush 2 点击上图的unipush2 0下面的配置 进入以下页面 选择平台 将其余项配置
  • tidb存储基本原理

    tidb是什么 tidb是分布式关系型数据库 需要从两个方面来理解tidb 分布式数据库 关系型数据库 什么是分布式系统 集中式系统 计算和存储在同一个节点上 分布式系统 计算和存储位于不同的节点上 分布式系统把需要进行大量计算的工程数据分
  • Unity3D持久化存储(一) PlayerPrefabs

    文章目录 PlayerPrefabs介绍 常用方法 存储数据 读取数据 查看数据 删除数据 PlayerPrefabs介绍 PlayerPrefabs是Unity内置的持久化存储类 可存储Float Int和String类型的数据 数据存储
  • AJAX传中文参数乱码问题解决

    当利用XMLHttpRequest提交中文数据到服务器端时候 ajax默认编码为utf8 提交中文会发生乱码 为了解决这个问题 baidu了一天 研究了一天 现在把这些心得写下来 以备忘 我这人健忘 首先明确一点 要想彻底没有乱码的烦恼 那
  • [论文阅读]《Database Maanagement Systems》-第三章

    第三章 THE RELATIONAL MODEL 关系模型 P75 P112 synopsis 概要 大纲 supplanted 代替 排挤掉 by far 到目前为止 Prototype relational database 原型关系数
  • Jetpack学习之Navigation

    Jetpack提供了一个名为Navigation的组件 用来管理页面 Actvity和Fragment 以Fragment为主 和App bar Navigation的优势 可视化的页面导航图 便于理清页面间的关系 通过destinatio