Navigation
Navigation
Navigation Graph
以下代码都可以通过拖拽生成
<?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/fragmentA">
<fragment
android:id="@+id/fragmentA"
android:name="com.example.testnavigation.FragmentA"
android:label="fragment_a"
tools:layout="@layout/fragment_a" >
<action
android:id="@+id/action_fragmentA_to_fragmentB2"
app:destination="@id/fragmentB" />
</fragment>
<fragment
android:id="@+id/fragmentB"
android:name="com.example.testnavigation.FragmentB"
android:label="fragment_b"
tools:layout="@layout/fragment_b" >
<action
android:id="@+id/action_fragmentB_to_fragmentC2"
app:destination="@id/fragmentC" />
</fragment>
<fragment
android:id="@+id/fragmentC"
android:name="com.example.testnavigation.FragmentC"
android:label="fragment_c"
tools:layout="@layout/fragment_c" />
</navigation>
navigation是根标签,通过startDestination配置默认启动的第一个页面,这里配置的是FragmentA
fragment标签代表一个fragment,其实这里不仅可以配置fragment,也可以配置activity,甚至还可以自定义
action标签定义了页面跳转的行为,相当于上图中的每条线,destination定义跳转的目标页,还可以定义跳转时的动画等等
当调用到 action_FragmentA_to_FragmentB2 这个 action,会从 FragmentA -> FragmentB
NavHostFragment
一种特殊的Fragment,用于承载导航内容的容器,存放在activity中
<?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">
<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:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
android:name
指定NavHostFragment
app:navGraph
指定导航视图,即建好的nav_graph.xml
app:defaultNavHost=true
意思是可以拦截系统的返回键,可以理解为默认给fragment实现了返回键的功能,这样在fragment的跳转过程中,当我们按返回键时,就可以使得fragment跟activity一样可以回到上一个页面了
通过NavController 管理fragment之间的跳转
打开FragmentA类,给布局中的TextView定义一个点击事件
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tv.setOnClickListener {
val navController = Navigation.findNavController(it)
navController.navigate(R.id.action_fragmentA_to_fragmentB2)
}
}
可以看到,通过navController管理fragment的跳转非常简单,首先得到navController对象,然后调用它的navigate方法,传入前面nav_graph中定义的action的id即可。
按同样的方法给FragmentB中的TextView也设置一个点击事件,使得点击时跳转到FragmentC
运行程序,FragmentA -> FragmentB -> FragmentC,此时按返回键,也是一个一个页面返回,如果把前面的app:defaultNavHost设置为false,按返回键后会发现直接返回到桌面。
app:defaultNavHost="true"属性可以确保NavHostFragment可以拦截系统的回退事件。你也可以重写AppCompatActivity.onSupportNavigateUp()方法并且调用NavController.navigateUp方法:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupActionBarWithNavController(findNavController(R.id.fcv))
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.fcv)
return navController.navigateUp() || super.onSupportNavigateUp()
}
}
跳转时通过 safeArgs 插件传递参数
这部分无所谓,直接使用bundle就行了
safeArgs会根据nav_graph中的fragment标签生成对应的类,
- action标签会以
“类名+Directions”
命名, - argument标签会以
“类名+Args”
命名
从home->detail
build 自动生成代码
接下来在Home_Fragment中
在Deatil中
NavigationUI
注意Menu中的id要和Navigation Graph中的id相对应
在MainActivity中
跳转后去掉导航栏,在对应的fragment中
最后在MainActivity中对页面的切换完成进行监听设置(addOnDestinationChangedListener)
该部分还可参考
https://blog.csdn.net/stephen_sun_/article/details/123716172?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168224198216800188586277%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168224198216800188586277&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-5-123716172-null-null.142^v86^insert_down1,239^v2^insert_chatgpt&utm_term=NavigationUI&spm=1018.2226.3001.4187
https://blog.csdn.net/qq_44408913/article/details/109076226
https://blog.csdn.net/qq_43404873/article/details/109515441
Reference:
https://blog.csdn.net/JMW1407/article/details/125714708
https://blog.csdn.net/mp624183768/article/details/126338041?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168223426716800182135271%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168223426716800182135271&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-126338041-null-null.142v86insert_down1,239v2insert_chatgpt&utm_term=navigateUp&spm=1018.2226.3001.4187
https://www.bilibili.com/video/BV1ma411R79w/?vd_source=5e78312fb5f90b9c83a318189a70a5c0