作用
统一管理Fragment,管理Ftagment之间跳转和Fragment与Activity的跳转,传参等。在项目中可以用Fragment来替换一部分Activity。
实现效果
基本使用
创建导航
右键res文件,new->Android Resource File显示如图
type选择Navigation,填入文件名OK就行,会自动生成一个navigation文件夹和一个xml文件
点击
添加已创建的Fragment
点击
设置一个Fragment为主Fragment,再用主Fragment的圆点连接至另一个Fragment表示跳转连接
自动生成的代码
<?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.jetpacklearn.FirstFragment"
android:label="fragment_first"
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.jetpacklearn.SecondFragment"
android:label="second_fragment"
tools:layout="@layout/second_fragment" />
</navigation>
app:startDestination="@id/firstFragment"表示起始点的Fragment, action中表示要跳转到的Fragment
另外一点,要在承载Fragment的Activity中添加一个NavHostFragment,用来显示Fragment。
activity_main.xml
<?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=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView4"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
其中android:name="androidx.navigation.fragment.NavHostFragment"是必须的,
app:navGraph="@navigation/nav_graph"为关联之前的导航xml文件
app:defaultNavHost="true"会拦截系统的返回按钮
Fragment跳转与传参
FirstFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val bundleOf = bundleOf("1" to "从First传递过来")
val str = arguments?.getString("2")
textView2.text = str
textView.setOnClickListener {
findNavController().navigate(R.id.action_firstFragment_to_secondFragment,bundleOf)
}
}
SecondFragment.kt
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val str = arguments?.getString("1")
textView3.text = str
val bundleOf = bundleOf("2" to "从SecondFragment传递过来")
textView4.setOnClickListener {
findNavController().setGraph(R.navigation.nav_graph,bundleOf)
}
textView7.setOnClickListener {
findNavController().navigate(R.id.action_secondFragment_to_secondActivity4)
}
}
获取NavController的方法
Fragment.findNavController()
View.findNavController()
Activity.findNavController(viewId: Int)
从Fragment跳转到Fragment,调用findNavController().navigate(),第一个参数为在导航图中的连接线的action id,第二个参数就是一个包装好的bundle对象。在接收参数的Fragemnt中获取bundle时还是调用getArgument()方法获取。
而Fragment回退时传参就需要调用 findNavController().setGraph(),第一个参数为导航图Navigation的id,第二个参数时bundle对象。如果回退时不需要传参就调用findNavController().navigateUp()就好。
如果需要从Fragment跳转到Activity,还是在导航图中新建一个Activity并用Fragment连线至该Activity,并自动生成action。跳转时还是调用findNavController().navigate()并传入action id。跳转到的Activity需要再用到Fragment的话就再从第一步开始套娃就好。
如果需要从Activity跳转到Activity则无此必要,Navigation也不支持。Navigation本身就是希望用Fragment来代替Activity,如果要这样实现其实用一个Activity创建宿主Fragment再用Fragment来实现跳转一个道理。
另外以我的理解,每个Activty中承载的多个Fragment的导航图都是单独的,也就是一个Activity会对应一个导航图。每个导航图最后目的地大部分也是另一个Activity。