思考几个问题:
图片.png
<?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/home_fragment">
<fragment
android:id="@+id/home_fragment"
android:name="org.devio.proj.navigationdemo.HomeFragment"
android:label="@string/hello_blank_fragment"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/home_to_other"
app:destination="@id/other_fragment"
app:enterAnim="@anim/fade_in"
app:exitAnim="@anim/fade_out" />
</fragment>
<fragment
android:id="@+id/other_fragment"
android:name="org.devio.proj.navigationdemo.OtherFragment"
android:label="@string/hello_blank_fragment"
tools:layout="@layout/fragment_other">
<action
android:id="@+id/other_to_deeplink"
app:destination="@id/nav_graph_to" />
<argument
android:name="home_arg_name"
android:defaultValue="defName"
app:argType="string"
app:nullable="true" />
<argument
android:name="home_arg_age"
android:defaultValue="99"
app:argType="integer" />
<argument
android:name="home_arg_mode"
app:argType="org.devio.proj.navigationdemo.Model" />
<!-- <deepLink-->
<!-- android:id="@+id/deepLink"-->
<!-- app:uri="www.baidu.com" />-->
<!-- android:autoVerify="false"
app:action="ACTION_SEND"
app:mimeType="text/html"-->
</fragment>
<navigation
android:id="@+id/nav_graph_to"
android:label="SecondHome"
app:startDestination="@id/deep_link_fragment">
<fragment
android:id="@+id/deep_link_fragment"
android:name="org.devio.proj.navigationdemo.DeeplinkFragment"
android:label="@string/hello_blank_fragment"
tools:layout="@layout/fragment_deeplink">
<action
android:id="@+id/deeplink_to_home"
app:popUpTo="@id/home_fragment" />
</fragment>
<fragment
android:id="@+id/settingFragment"
android:name="org.devio.proj.navigationdemo.SettingFragment"
android:label="fragment_setting"
tools:layout="@layout/fragment_setting" />
</navigation>
</navigation>
==navigation== :视图导航的根部标签, ==app:startDestination="@id/home_fragment"== 指定以哪个页面为首页。<navigation> 标签下包含3中子标签。:
<activity></activity> 支持Activity 跳转
<dialog></dialog> 支持 dialogFragment 跳转
<fragment></fragment> 支持fragment 跳转
出以上三种跳转类型外,==</navigation>== 标签下还支持嵌套操作。
<navigation>
<navigation>
</navigation>
<include >// 嵌套另一个nav_graph ,注意:
这个布局只能是<navigation>为根节点的布局
</include>
</navigation>
以Fragment为例,创建3个Fragment实例,分别为HomeFragment,OtherFragment,DeeplinkFragment。
<?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/home_fragment">
<fragment
android:id="@+id/home_fragment"
android:name="org.devio.proj.navigationdemo.HomeFragment"
android:label="@string/hello_blank_fragment"
tools:layout="@layout/fragment_home">
</fragment>
<fragment
android:id="@+id/other_fragment"
android:name="org.devio.proj.navigationdemo.OtherFragment"
android:label="@string/hello_blank_fragment"
tools:layout="@layout/fragment_other">
</fragment>
<navigation
android:id="@+id/nav_graph_to"
android:label="SecondHome"
app:startDestination="@id/deep_link_fragment">
<fragment
android:id="@+id/deep_link_fragment"
android:name="org.devio.proj.navigationdemo.DeeplinkFragment"
android:label="@string/hello_blank_fragment"
tools:layout="@layout/fragment_deeplink">
<action
android:id="@+id/deeplink_to_home"
app:popUpTo="@id/home_fragment" />
</fragment>
<fragment
android:id="@+id/settingFragment"
android:name="org.devio.proj.navigationdemo.SettingFragment"
android:label="fragment_setting"
tools:layout="@layout/fragment_setting" />
</navigation>
</navigation>
id 当前节点的唯一标识
name <fragment/> 节点对应的Fragment全类名
label 节点说明,当与BottomNavigationView组合使用时,字符串内容会成为页面的title
tools:layout coding时,查看界面内容
==注:== 节点的含义,即表示 <Activity> <Fragment>,<DialogFragment>
图片.png
点击右上角Design,进入Navigation,视图导航编辑页面。左侧为添加一个
图片.png
新节点,
图片.png
设置某个节点,为首页第一个展示节点。
==右侧是为节点添加支持的属性:==
图片.png
跳转,回退当前节点所需要的参数。
Name: 参数名称,等同于intent.getString(key,value)中的Key Type: 参数类型 Array: 是否是数组(String[]) Nullable: 是否可以为空 Default Value 为空的时的默认值
更多支持的参数类型:
图片.png
图片.png
ID 当前跳转动作节点的唯一标识,后续在代码中调用navController.navigation(R.id.ID)会用到,即执行当前配置的Action From 所配置的当前节点,点击给那个节点配置,默认就是哪个。选中后不可更改 Destination 跳转的目标节点,即那个Fragment enter:进入动画 Exit :退出动画 Pop Enter : 上一节点出栈当前节点的动画 Pop Exit: 上一节点回退栈到当前节点的动画
Pop To 按返回键会调用 navController.navigationUp或navController.popBackStack()时,想回退定向到那个节点
Inclusive: 很重要 多次出现。加入A->B->C,C的Pop To为B,当Inclusive 为true,则表示B也退出,直接进入到A,false回退到B Single Top 类似Activity的SingleInscance,管理栈中有相同的节点,则不会创建,同时栈内此节点的上面的节点,全部出栈。
<deepLink
android:id="@+id/deepLink"
android:autoVerify="false"
app:action="ACTION_SEND"
app:mimeType="text/html"
app:uri="www.baidu.com" />
理解nav_graph.xml后,在MainActivity中配置如下配置文件:
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
以上3个配置比较重要:
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
android:name="androidx.navigation.fragment.NavHostFragment"
三个必配项。
Acitivty#findNavController() 传入navGraph id Fragment#findNavController() 直接调用 Navigation.findNavController() 传入View
==navController.navigate()==
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val homeText = view.findViewById<TextView>(R.id.home_text)
homeText.setOnClickListener {
val model = Model("Jack", 16)
val bundle = Bundle()
bundle.putString("home_arg_name", "Tom")
bundle.putInt("home_arg_age", 12)
bundle.putParcelable("home_arg_mode", model)
// arguments?.let {
// it.putString("home_arg_name", "Tom")
// it.putInt("home_arg_age", 12)
// it.putParcelable("home_arg_mode", model)
// }
// val navOptions = navOptions {
// arguments?.let {
// it.putString("home_arg_name", "Tom")
// it.putInt("home_arg_age", 12)
// it.putParcelable("home_arg_mode", model)
// }
// }
findNavController().navigate(R.id.home_to_other, bundle)
// findNavController().navigate(R.id.home_to_other)
// findNavController().navigateUp()
// findNavController().popBackStack()
}
}
navigate() 传入节点ID 表示路由到节点所在页面, 传入Action ID 表示执行XML <Action>中的路由规则,同时还支持Deeplink跳转
navigateUp()和popBackStack()都表示回退上页面,但navigateUp()在Deeplink的情况下 应用1a(deeplink)路由到应用2的B后navigateUp()返回到a,而popBackStack()则会返回到当前栈内的上一层(A) 另一个区别是popBackStack()支持回退到指定页面,inclusive参数,之前有提到过
bundle 设置传递参数 Options设置其他配置参数,如动画,popUpTo等,也就说,在XML中的配置,在代码中都可实现。 那么参数中的配置argument在什么场景下比较合适。答案是:一些固定配置参数。例如loginFragment。A,B页面都会进入Login页面,但它们有不同的权限,所以可以配置不同的type,且这种配置基本不会变化。
未命名文件.png
下篇将从这张图入手,开始源码分析,并利用实战改造