Android Jetpack - 使用 Navigation 管理页面跳转

在今年的 IO 大会上,发布了一套叫 Android Jetpack 的程序库。Android Jetpack 里的组件大部分我们都接触过了,其中也有一些全新的组件,其中一个就是 Navigation。

简介

Navigation 是用来管理 APP 里页面跳转的。起初,我以为它是用来代替 startActivity 的,但其实并不是,大家往下看就知道它的作用了。

另外,iOS 的同学可能会有似曾相识的感觉,Navigation 应该是有借鉴 Storyboard 的。

使用

我们先来看看 Navigation 的实现过程。

添加依赖

首先,需要使用 Android Studio 3.2 以上版本才能使用 Navigation。

在 build.gradle 中添加依赖:

implementation "android.arch.navigation:navigation-fragment:$nav_version"
implementation "android.arch.navigation:navigation-ui:$nav_version"

创建 navigation xml 文件

使用 「Android Resource File」创建 xml 文件的时候,可以看到在类型里,多了一个 Navigation 的选项:

创建成功后,就来到了文章开头的那个一个可视化的操作界面。点击左上角的添加小图标,会出现 Activity 和 Fragment,我们这里添加两个 Activity 和两个 Fragment:

配置 Action

Fragment 的右边有个小圆圈,点击并拖到另一个页面,这样我们就给这个 Fragment 添加了一个跳转行为,也就是 Action。

但是可以发现,Activity 的右边是没有这个小圆圈的,所以 Navigation 并不能处理从 Activity 发起的跳转。

左上角有个小房子的是显示的第一个页面,但由于 Activity 无法发起跳转,所以这里把 MainActivity 删除,把 MainFragment 作为主页面,并给它添加跳转到 SecondFragment 和 SecondActivity 的 Action:

自动生成的 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/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.navigation.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_mainFragment_to_secondFragment"
            app:destination="@id/secondFragment"
            app:enterAnim="@anim/slide_in_right" />
        <action
            android:id="@+id/action_mainFragment_to_secondActivity"
            app:destination="@id/secondActivity" />
    </fragment>
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.example.navigation.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second" />
    <activity
        android:id="@+id/secondActivity"
        android:name="com.example.navigation.SecondActivity"
        android:label="activity_second"
        tools:layout="@layout/activity_second" />

</navigation>

布局中添加 Fragment

现在,我们第一个页面是 MainFragment,而 Fragment 需要 Activity 作为容器,修改 MainActivity 的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav" />

</FrameLayout>

其中有三个属性需要注意。使用 android:name 指定 Fragment 的类型为 NavHostFragment,使用 app:navGraph 指定 Navigation 文件。app:defaultNavHost="true" 的作用是,让 Navigation 处理返回事件,点返回按钮时并不是返回上一个 Activity,而是返回上一个「页面」,上一个「页面」有可能是 Activity,也可能是 Fragment。

至此,Navigation 的简单配置就算完成了,接下来看如何使用它。

配置跳转

在 Navigation 里,页面的跳转是交给 NavController 来处理的,获取 NavController 的方法有这么三种:

NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, @IdRes int viewId)
Navigation.findNavController(View)

拿到后,通过 navigate 方法,通过传入 Action 的 id,实现跳转,比如:

NavHostFragment
            .findNavController(this)
            .navigate(R.id.action_firstFragment_to_secondFragment)

在简单配置了两个跳转后,看一下目前的效果:

传参

页面的跳转少不了数据的传递,使用 Navigation,和我们原来的跳转一样,可以通过 Bundle 来传递参数:

val bundle = Bundle()
bundle.putString("name", "SouthernBox")
NavHostFragment
            .findNavController(this)
            .navigate(R.id.action_firstFragment_to_secondFragment, bundle)

如果跳转到 Activity,可以从 intent.extras 获取到 bundle,如果是 Fragment,则从 arguments 获取到。

此外,还可以在 Navigation 的 xml 文件中配置传参,但这种方式目前支持的数据类型比较少,连 boolean 都不支持,而且我还碰到了 bug,所以目前不建议用。

转场动画

如果需要自定义的页面转场动画,使用 Navigation 可以很方便的实现。

这里举个例子,比如我们需要一个从右向左切入的过场动画,先创建这个动画的 xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate
        android:duration="600"
        android:fromXDelta="100%"
        android:toXDelta="0" />

</set>

然后我们回到 Navigation 的可视化编辑页面来,点击跳转的线,右边会出现过场动画的配置选项,将 xxxx 设为刚才创建的动画:

这么简单就搞定了,效果如下:

Navigation 的使用介绍就到这里。

思考

你可能已经明白,Navigation 主要是用来处理 Fragment 的跳转,所以说它并不是用来代替 startActivity,而是用来代替 FragmentTransaction 的相关操作。

在官方文档里,可以看到一个将传统跳转迁移到 Navigation 的建议。我简单理解为,将原本两个 Activity 之间的跳转,逐渐修改为使用一个 Activity 作为容器,用两个 Fragment 作为页面跳转。

看到这里,我联想到了在去年,Jake Wharton(目前在谷歌)有这么一个有争议的言论:

“一个 APP 只需要一个 Activity。”

在过去,要实现这种方式,就需要去解决复杂的 Fragment 堆栈处理,而且早期的 Fragment 坑比较多,处理不好容易出现页面穿透等问题。现在 Navigation 恰好解决了这些问题。

这一切联系起来,是不是能说明官方间接支持了「少用 Activity 多用 Fragment」的做法?你怎么看?

原文地址:https://www.cnblogs.com/1157760522ch/p/10944420.html

时间: 2024-08-29 10:38:33

Android Jetpack - 使用 Navigation 管理页面跳转的相关文章

Android混合应用开发之页面跳转

Android混合开发之Activity类与html页面之间的相互跳转(并解决黑屏问题) 在底部有本程序源码下载 本程序流程:程序启动-->testActivity--->phonegap2框架类--->index.html--->testActivity,主要实现activity与html页面的相互跳转,并实现 传递参数的功能. 程序结构图: 1.创建一个安卓项目,在该项目里面添加PhoneGap框架(具体步骤请点击查看),我们知道我们在定义一个主界面的时候往往用的是Activi

Android 完美解决bundle实现页面跳转并保留之前数据+传值

前言:昨天碰到了一个问题,我想实现页面跳转,采用了Bundle之后,再回到原来的页面,发现数据也没有了,而且一直报错,网上查找了很多资料,发现要用一个startActivityForResult(),然而好景不长,我又想在后面的页面把后面页面的数据和前面传过来的数据都传递给中间页面的数据,这样挺起来有些复杂,我简单写了一个Demo 1.首先是3个Activity=====对应3个布局=====全部贴出来好了,一看就懂的. 对应Main3Activity <?xml version="1.0

Android自学笔记之Intent 页面跳转详解

Intent:意图,协助完成Android各个组件之间的通讯    实现跳转功能有两种实现方式:1.无返回值的跳转 2.有返回值的跳转 一.无返回值的跳转实现需要用到的方法:startActivity(intent) 二.有返回值的跳转实现需要用到的方法: startActivityForResult(intent,requestCode)//有返回值 onActivityResult(int requestCode,int resultCode,Intent data)//接收返回值A页面 s

Android中实现activity的页面跳转并传值

一个Android应用程序很少会只有一个Activity对象,如何在多个Activity之间进行跳转,而且能够互相传值是一个很基本的要求. 本次我们就讲一下,Android中页面跳转以及传值的几种方式! Activity跳转与传值,主要是通过Intent类来连接多个Activity. 1. Intent显式意图 (1) 最常见最一般的页面跳转代码,很简单,如下: Intent intent = new Intent(A.this, SecondActivity.class); startActi

android studio真机测试页面跳转时自动弹出软件,报错null exception解决方案

写的ASdemo登录页面后将实现页面跳转,可以看到跳转页面后自动弹出软件,查看AS的logcat说明错误原因时java的空指针问题! 解决方案: 查看新的页面(activity)代码是否存在空指针!发现我的一个String 类型的变量存在直接判等操作eg: if ( !name[0].equals("F") ) { ..... },这句话有问题,由于我的name字符串里面的值来自于其他数据库操作获取数据,全局变量只声明未初始化,在参与计算时先判断一下是否为null! 所以先判断if (

.Net程序员玩转Android开发---(11)页面跳转

在任何程序开发中,都会遇到页面之间跳转的情况,Android开发也不例外.这一节,我们来认识下Android项目中怎样进行页面跳转.页面跳转分为有参数和无参数页面跳转,已经接受另一个页面的返回值等.Android中页面跳转常用到的是Intent ,但是Intent不仅用做页面跳转,还可以做其他事情,例如拨打电话,发送短信,调用其他程序等.这节我们主要认识下怎样通过Intent进行页面跳转. 1.页面跳转 2.带参数页面跳转

Android各大手机系统打开权限管理页面

最近项目上比较忙,终于有空闲时间写写东西了. 相信做过Android的都知道,现在的手机系统五花八门,当我们去请求用户的权限的时候,总是会弹出是否允许的对话框. 而且用户一旦不小心点了拒绝,下次就不再询问了,而很多小白用户也不知道怎么去设置.这就导致了很不好的用户体验. 经过研究,我发现像小米,魅族,这些满大街的系统,都是可以通过隐式意图打开权限设置页面的. 这里指的是自身app的权限管理页面 之前已经有人写过类似的文章,不过都比较分散,我这里把这些方法总结了一下. 不多说,直接上代码. 首先是

2015 IOS 学习笔记 内存管理,页面跳转 ——蓝懿教育

——————————内存管理———————————————— 手动内存管理(MRC)中常用的三个方法 retain:导致内存计数+1 release:导致内存计数-1 copy:复制出来一个新的对象 和之前对象的数据可能一致 但是 不是同一个对象 此对象内存计数是1 autorelease:自动释放 当变量出了自动释放池之后会自动释放 自动释放池在项目中有很多看不见的 属性描述关键字: retain/strong: //如果是retain 会做两件事 //-(void)setNames:(NSM

Android页面跳转和数据传递

Android应用开发-页面跳转和数据传递 Activity Android四大组件之一 可以理解为Android中的界面,每一个界面都是一个Activity Activity的使用必须在清单文件中进行配置 在清单文件中, 创建第二个Activity 需要在清单文件中为其配置一个activity标签 标签中如果带有这个子节点,则会在系统中多创建一个快捷图标 <intent-filter> <action android:name="android.intent.action.M