在这篇博客中,我们将讨论Jetpack的Navigation Component。假设你已经掌握了Android的基本知识,并且渴望精通Android。
什么是 JetPack?
Jetpack是在Google I/O 2018上推出的一套UI组件库,用于帮助开发人员遵循最佳实践,减少样板代码,并编写能够在Android不同版本和设备之间一致工作的代码,以便开发人员能够只专注于写他们关心的代码。
不使用Navigation component
- 应用程序中的导航任务是手动创建的
- 没有创建/编辑应用程序路由导航流的标准实践
- 没有标准的可视化工具来理解应用程序路由流程
- 没有一致的方法将
Activity/Fragment管理到本机应用程序中
使用Navigation component
- 现在,我们有了标准的API,以及还有IDE中的可视化工具,用以帮助使整个开发过程更加清晰、简单和一致
- 我们可以使用设计工具来创建路由并定义导航路径
先决条件
导航组件需要Android Studio 3.3或更高版本,并且依赖于Java 8语言特性。
简单介绍
不同屏幕和应用程序中,路由导航是用户体验的核心部分。一些原则为跨应用程序的一致和直观的用户体验设定了一个基准。Navigation component被设计为默认实现这些原则,确保用户在不同应用程序之间,可以有相同的启发式和模式的导航体验。
Navigation是一个用于在Android应用程序中不同页面之间跳转导航的框架,它提供了一致的API,无论目的页面是以Activity或Fragment还是其他组件的形式实现的。
Navigation Component由三个部分组成:
Navigation Graph(XML resource): 这个一个包含所有导航页面的文件。它包含应用中所有的Activities、Fragments和Dialogs,以及用户在应用中可能经过的所有路径。- NavHostFragment(Layout XML view): 这是一个布局中的特殊组件,它用于显示不同页面的路径
- NavController (Kotlin/Java object): 这是一个
Navigation控制器,当你在不同页面跳转时,它可以用来控制跳转及获取当前位置。
如何使用
步骤一: 在build.gradle中添加依赖
dependencies {
def nav_version = “2.3.2"
// Java依赖
implementation “androidx.navigation:navigation-fragment:$nav_version"
implementation “androidx.navigation:navigation-ui:$nav_version"
// Kotlin依赖
implementation “androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation “androidx.navigation:navigation-ui-ktx:$nav_version"
// Feature 模块依赖
implementation “androidx.navigation:navigation-dynamic-features-fragment:$nav_version"
// 测试模块
androidTestImplementation “androidx.navigation:navigation-testing:$nav_version"
}
步骤二: 向Activity中添加NavHost
- 这是一个Activity的布局,它包含全局导航,一个底部按钮和一个工具栏
android:name="androidx.navigation.fragment.NavHostFragment"和app:defaultNavHost="true"将系统的后退按钮连接到NavHostFragmentapp:navGraph="@navigation/app_navigation"用于将NavHostFragment与Navigation Graph联系起来,Navigation Graph用于管理所有路由导航。
步骤三: 创建nav_graph文件(Navigation Graph)
它用于将所有页面路由作为子元素添加到一个文件中。注意,请确保所有子元素都分配了唯一的id。
IDE路由提供的路由编辑器
自动生成的源码
这里使用了四个参数:
android:id: 路由唯一id,跟之前在XML中为其它组件设置id类似android:name: 路由使用的类名android:label: 路由名称tools:layout: 布局文件的id
我们使用startDestination来定义第一个视图位置
我们再来看看action中使用的参数
android:id:action的idapp:destination: 目标页面的id,将当前action跟页面联系起来app:popUpTo: 如果应用程序已经从页面A导航到页面B,然后从页面B导航到页面C,那么这是为了向后导航。如果要将页面A转到页面C,可以将页面A的id设置到这里。后台导航组件将会自动管理堆栈和生命周期。popUpToInclusive=true: 表示返回到popUpTo指定的页面后,会清除的栈顶的页面。- 我们还可以定义一些导航动画,我们可以在
res/anim文件夹中定义好动画
<fragment
android:id="@+id/loginFragment"
android:name="com.android.samples.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login" >
<action
android:id="@+id/action_loginFragment_to_forgotPasswordFragment"
app:destination="@id/forgotPasswordFragment"
app:popUpTo="@+id/signinMainFragment"
app:popUpToInclusive="true"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"/>
<action
android:id="@+id/action_loginFragment_to_tnCFragment"
app:destination="@id/tnCFragment" />
</fragment>
我们可以定义动画使用下面的属性:
- app:enterAnim="@anim/slide_in_right"
- app:exitAnim="@anim/slide_out_left"
- app:popEnterAnim="@anim/slide_in_left"
- app:popExitAnim="@anim/slide_out_right"
跳转页面(NavController)
NavController非常强大,因为当您调用像navigate()或popBackStack()这样的方法时,它会将这些命令转化为框架兼容的方法。例如,当你调用navigate()时,NavController会内部调用startActivity()。
跳转页面使用NavController完成的,这是一个管理NavHost中的应用导航的对象。每个NavHost都有自己对应的NavController。你可以使用以下方法之一来获取一个NavController:
Kotlin:
Java:
- NavHostFragment.findNavController(Fragment)
- Navigation.findNavController(Activity, @IdRes int viewId)
- Navigation.findNavController(View)
Navigation component推荐使用Safe Args这个Gradle插件确保类型安全
我们可以获取一个NavController对象,并通过navigate来跳转
val directions: NavDirections = LoginFragmentDirections.actionLoginFragmentToForgotPasswordFragment()
Navigation.findNavController(view).navigate(directions)
嵌套路由
我们可以将一些路由进行嵌套,以重用一些组件。我们可以使用include来进行设置
<include app:graph="@navigation/profile_nav_graph" />
使用NavigationUI跳转
我们可以在页面共用的如顶部导航栏通过NavigationUI来进行页面跳转