Navigation 直接翻译即为导航,它是 Android Jetpack 组件之一,让单 Activity 应用成为首选架构。应用内Fragment页面的跳转则由 Navigation 来处理,开发者无需在处理 FragmentTransaction 的复杂性以及相关的转场动画。
相比之前Fragment的管理需要借助FragmentManager和FragmentTransaction,使用Navigation组件有如下一些优点:
1.可视化的页面导航图,方便我们理清页面之间的关系
2.通过destination和action完成页面间的导航
3.方便添加页面切换动画
4.页面间类型安全的参数传递
5.通过Navigation UI类,对菜单/底部导航/抽屉蓝菜单导航进行统一的管理
实战完成效果
使用Navigation
1. 引入依赖
在app的gradle.build中添加依赖:
nav_version=2.5.0
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
2. 了解组成
Navigation graph
一个包含所有导航相关信息的 XML 资源
xml 档,包含所有被管理的 Fragment,起始目标,换页目标,返回目标。NavHostFragment
一种特殊的Fragment,用于承载导航内容的容器NavController
用来管理 NavHost 中的导航动作,通常是写在点击事件内完成 Fragment 的切换。
findNavController().navigate(R.id.action_Fragment1_to_Fragment2)
3.开始接入
1.右键res,点击New -> Android Resource Directory
2.在出现的面板第二行Resource type 下拉列表中选择 Navigation,然后点击 OK
3.res目录下会多出一个navigation的资源目录,右键该目录,点击New -> Navigation Resource File,输入需要新建的资源文件名,这里命名nav_graph,点击ok,一个nav_graph.xml就创建好了。
新建好的nav_graph.xml切换到design模式下,点击2处的加号,选择Create new destination,即可快速创建新的Fragment。或者直接引用已有的fragment做管理。
建好后,可通过手动配置页面之间的跳转关系,点击某个页面,右边会出现一个小圆点,拖曳小圆点指向跳转的页面,这里设置跳转的关系为FragmentA -> FragmentB。
<?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"
android:id="@+id/nav_graph"
app:startDestination="@id/navigation_home">
<fragment
android:id="@+id/navigation_home"
android:name="com.example.flowmvihilt.ui.main.MainFragment">
<action android:id="@+id/action_to_artical"
app:destination="@id/articalFragment"/>
</fragment>
<fragment
android:id="@+id/navigation_qa"
android:name="com.example.flowmvihilt.ui.main.MainFragment" />
<fragment
android:id="@+id/navigation_system"
android:name="com.example.flowmvihilt.ui.main.MainFragment"
android:label="MainFragment" />
<fragment
android:id="@+id/navigation_mine"
android:name="com.example.flowmvihilt.mine.MeFragment"/>
<fragment
android:id="@+id/articalFragment"
android:name="com.example.flowmvihilt.mine.ArticalFragment"/>
</navigation>
navigation是根标签,通过startDestination配置默认启动的第一个页面,这里配置的是FragmentA
fragment标签代表一个fragment,其实这里不仅可以配置fragment,也可以配置activity,甚至还可以自定义
action标签定义了页面跳转的行为,相当于上图中的每条线,destination定义跳转的目标页,还可以定义跳转时的动画等等
当调用到 action_FragmentA_to_FragmentB2 这个 action,会从 FragmentA -> FragmentB
在Activity的布局文件中配置NavHostFragment和BottomNavigationView
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:itemBackground="@null"
app:menu="@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
android:name指定NavHostFragment
app:navGraph指定导航视图,即建好的nav_graph.xml
app:defaultNavHost=true意思是可以拦截系统的返回键,按返回键可以回到上一个页面
menu文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/home_page" />
<item
android:id="@+id/navigation_qa"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/q_a" />
<item
android:id="@+id/navigation_system"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/system" />
<item
android:id="@+id/navigation_mine"
android:icon="@drawable/ic_launcher_foreground"
android:title="@string/mine" />
</menu>
将Navigation与BottomNavigationView关联
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navView.setupWithNavController(navHostFragment.findNavController())
通过NavController 管理fragment之间的跳转
findNavController().navigate(R.id.action_to_artical)
navigate方法传入配置的某个action来进行跳转。
跳转传递参数
var args = Bundle()
args.putString("params", "params")
Navigation.findNavController(btnHome).navigate(R.id.fragment_home_to_fragment_msg, args)
目标页接收参数:
var params = arguments?.getString("params")
导航文件拆分
如果项目越来越大,页面越来越多,所有的都放在一个文件中会非常的臃肿,当Action非常复杂的时候会非常的混乱。那么可创建多个navigation.xml进行导航。
Deeplink导航
Navigation也能通过Deeplink进行跳转。如下:
findNavController().navigate(Uri.parse("schema://webview.fragment"))
参考:
https://blog.csdn.net/JMW1407/article/details/125714708
https://blog.csdn.net/lcl130/article/details/108422026