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」的做法?你怎么看?
Android Jetpack - 使用 Navigation 管理页面跳转的更多相关文章
- Android中实现activity的页面跳转并传值
一个Android应用程序很少会只有一个Activity对象,如何在多个Activity之间进行跳转,而且能够互相传值是一个很基本的要求. 本次我们就讲一下,Android中页面跳转以及传值的几种方式 ...
- Android 完美解决bundle实现页面跳转并保留之前数据+传值
1.前言 前言: 昨天碰到了一个问题,我想实现页面跳转,采用了Bundle之后,再回到原来的页面,发现数据也没有了, 而且一直报错,网上查找了很多资料,发现要用一个startActivityForRe ...
- Android Jetpack Navigation基本使用
Android Jetpack Navigation基本使用 本篇主要介绍一下 Android Jetpack 组件 Navigation 导航组件的 基本使用 当看到 Navigation单词的时候 ...
- .Net程序猿玩转Android开发---(11)页面跳转
在不论什么程序开发中,都会遇到页面之间跳转的情况,Android开发也不例外.这一节,我们来认识下Android项目中如何进行页面跳转.页面跳转分为有參数和无參数页面跳转,已经接受还有一个页面的返回值 ...
- [Xcode 实际操作]九、实用进阶-(24)使用Segue(页面的跳转连接)进行页面跳转并传递参数
目录:[Swift]Xcode实际操作 本文将演示使用Segue(页面的跳转连接)进行页面跳转并传递参数. 参照结合:[Xcode10 实际操作]九.实用进阶-(23)多个Storyboard故事板中 ...
- Android各大手机系统打开权限管理页面
最近项目上比较忙,终于有空闲时间写写东西了. 相信做过Android的都知道,现在的手机系统五花八门,当我们去请求用户的权限的时候,总是会弹出是否允许的对话框. 而且用户一旦不小心点了拒绝,下次就不再 ...
- Android 7.0 Gallery图库源码分析4 - SlotView手势监听及页面跳转
上篇文章讲了初始化View时会实例化一个SlotView并监听其事件,至于它是怎么实现的,用的是Android自带的GestureDetector. GestureDetector是Android自带 ...
- Android first --- 页面跳转及数据传递
页面跳转即数据传递 创建第二个界面Acivity *需要在清单文件中添加配置一个Actuvity标签 标签中如果带有这个子节点,则会在Android中添加一个快捷图标 <intent-filte ...
- android 学习第一天 了解事件机制,页面跳转等常用操作
点击时间2种 第一种,通过初始化页面 写入点击事件 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedI ...
随机推荐
- git添加user及repository
- linux more-显示文件内容,每次显示一屏
博主推荐:获取更多 linux文件内容查看命令 收藏:linux命令大全 more命令是一个基于vi编辑器文本过滤器,它以全屏幕的方式按页显示文本文件的内容,支持vi中的关键字定位操作.more名单中 ...
- Tampermonkey脚本安装问题及自用脚本推荐
对于高手来说,chrome浏览器中即使没有其他任何chrome插件,可能都无关紧要.但是有一个插件必不可少, 那就是Tampermonkey油猴插件.Tampermonkey是Chrome上最流行的用 ...
- Wind rotor states
test test Table of Contents 1. Wind rotor states 1.1. Turbulent Wake State 1.2. Vortex Ring State 1. ...
- streamwise veloicty along the jet axis using Matlab/Octave
input file: v.csv scpirts as follows filename='v.csv'; % assign file to a variable m=csvread(filenam ...
- PAT 1146 Topological Order
This is a problem given in the Graduate Entrance Exam in 2018: Which of the following is NOT a topol ...
- 九度oj 1179 阶乘
题目1179:阶乘 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6010 解决:1756 题目描述: 输入n,求y1=1!+3!+...m!(m是小于等于n的最大奇数)y2=2!+4!+ ...
- [K/3Cloud]屏蔽页签的关闭按钮
如图,屏蔽企业门户的X关闭按钮. this.View.GetControl<TabControl>("FMainTab").SetItemCloseable(1, fa ...
- html+css使图片在页面中循环滚动
我们先通过html创建一个div盒子的框架,方便后续以及实际使用中调整位置. <!DOCTYPE html> <html> <head> <meta char ...
- Spring Cloud ZooKeeper集成Feign的坑2,服务调用了一次后第二次调用就变成了500,错误:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.n
错误如下: 2017-09-19 15:05:24.659 INFO 9986 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refre ...