最全⾯的Navigation的使⽤指南
Navigation可以⽬前看做Google对于之前的Fragment的不满, 重新搭建的⼀套Fragment管理框架. 但是Navgation未来应该不仅限于Fragment导航.
并且Navigation可以和BottomNavigationView/NavigationView/Toolbar等结合使⽤, 不再需要去写冗余代码管理Fragment.
并且具备完善的Fragment回退栈管理.
如果是使⽤Java语⾔我不推荐使⽤任何新框架了, 就⾃⼰玩⾃⼰的吧.
ktx (除基本依赖外还包含⼀些Kotlin新特性的函数)
implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.0.0'
复制代码
⼀些常⽤的关键字解释
navigation(nv): 导航, 即Navigation框架的fragment返回栈
graph: 指⼀个描述返回栈关系的xml⽂件 (NavigationResourceFile) 也是布局编辑器⽤于显⽰图表的界⾯数据来源
destination: ⽬标, 即在返回栈中要跳转的新页⾯
pop: 弹出栈, 会弹出所有不符合⽬标的页⾯, 直⾄到⽬标页⾯(默认情况不弹出⽬标页⾯也可以设置), 可以理解为Fragment的singleTask 模式
navHost: 即所有页⾯的容器. 类似⽹页中的host, 所有path路径都是在host之后跟随, host固定不变.
XML编辑
点击NavResourceFile中的Design即可查看布局编辑器, 布局编辑器分为三栏.
左侧是已添加的导航, 中间是页⾯浏览, 中间栏的⼯具栏可以创建和快速添加标签以及整理页⾯, 右侧属性栏⽅便添加属性.
navigation这是个嵌套的图表, 可以点击打开新的图表页⾯.
Activity布局中
<LinearLayout
.../>
<androidx.appcompat.widget.Toolbar
.../>
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/mobile_navigation"
app:defaultNavHost="true"
/>
&le.android.material.bottomnavigation.BottomNavigationView
.../>
</LinearLayout>
复制代码
android:name="androidx.navigation.fragment.NavHostFragment"
固定写法
app:navGraph
指定navigation资源⽂件, 也可以不指定后⾯通过代码中动态设置
app:defaultNavHost
是否拦截返回键事件, false表⽰不需要回退栈.
复制代码
NavigationResourceFile
res⽬录创建 AndroidResourceFile 选择 Navigation. 然后 new-> NavigationResourceFile navigation
app:startDestination="@+id/home_dest" 指定初始⽬标
复制代码
navigation可以嵌套navigation标签.
在布局编辑器中会显⽰为
嵌套navigation⽆法互相关联
<navigation
xmlns:android="schemas.android/apk/res/android"
xmlns:app="schemas.android/apk/res-auto"
xmlns:tools="schemas.android/tools"
android:id="@+id/nav_global"
app:startDestination="@id/mainFragment">
<!-- <action
android:id="@+id/global_action"
app:destination="@id/navigation" />-->
<fragment
android:id="@+id/mainFragment"
android:name="ample.frameexample.MainFragment"
android:label="fragment_main"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/action_mainFragment_to_personInfoFragment"
app:destination="@id/settingFragment" />
</fragment>
<navigation
android:id="@+id/navigation"
app:startDestination="@id/settingFragment">
<fragment
android:id="@+id/settingFragment"
android:name="ample.frameexample.SettingFragment"
android:label="fragment_setting"
tools:layout="@layout/fragment_setting" />
</navigation>
</navigation>
复制代码
上⾯的mainFragment⽆法直接app:destination="@id/settingFragment"这会导致运⾏错误. 只能先导航到navigation.(即NavHostFragment 所在的界⾯)
fragment
android:id 不⾔⽽喻
android:name ⽬标要实例化的fragment完全限定类名
tools:layout ⽤于显⽰在布局编辑器
android:label ⽤于后⾯绑定Toolbar等⾃动更新标题
复制代码
argument
android:name="myArg"
app:argType="integer"
android:defaultValue="0"
复制代码
参数名称
参数类型
参数默认值
在跳转导航页⾯的时候会⾃动在argument中带上参数(要求指定参数默认值). 数组和Paraclable/Seriali
zable不⽀持默认值设置, 通过下⾯要讲的SafeArg可以在编译器校验参数类型安全问题.
action
动作 ⽤于页⾯跳转时指定⽬标页⾯
android:id="@+id/next_action"
动作id
app:destination="@+id/flow_step_two_dest">
⽬标页⾯
app:popUpTo="@id/home_dest"
当前属于弹出栈
app:popUpToInclusive="true/false"
弹出栈是否包含⽬标
app:launchSingleTop="true/false"
是否开启singleTop模式
app:enterAnim=""
app:exitAnim=""
导航动画
app:popEnterAnim=""
app:popExitAnim=""
弹出栈动画
复制代码
如果从导航页⾯到新的Activity页⾯, 动画不⽀持. 请使⽤默认的Activity设置动画去⽀持.
全局动作
⼀般情况下NavController只能使⽤当前Fragment在NavXML中声明的⼦标签action, 但是可以通过直接给navigation标签创建⼦标
签action实现全局动作, 即每个Fragment都能使⽤的动作.
给navigation添加action⼦标签时要求给navigation指定熟悉android:id
占位页⾯如果运⾏时没有指定Class并且导航到该占位页⾯时会抛出异常
类关系
涉及到的类关系
NavController 控制导航的跳转和弹出栈
NavOptions 控制跳转过程中的配置选项, 例如动画和singleTop模式
Navigation ⼯具类 创建点击事件或者获取控制器
NavHostFragment 导航的容器, 可以设置和获取导航图(NavGraph)
NavGraph ⽤于描述导航中页⾯关系的对象 可以增删改查页⾯,设置起始页等
NavigationUI ⽤于将导航和⼀系列菜单控件⾃动绑定的⼯具类
Navigator 页⾯的根接⼝, 如果想创建⼀个新的类型页⾯就要⾃定义他
NavDeepLinkBuilder 构建⼀个能打开导航页⾯的Intent
NavController
NavController⽤于跳转页⾯和参数传递等控制, 可以通过扩展函数得到实例.
Fragment.findNavController()
View.findNavController()
Activity.findNavController(viewId: Int)
复制代码
导航
public final void navigate (int resId)
public final void navigate (int resId,
Bundle args)
public void navigate (int resId,
Bundle args,
NavOptions navOptions)
public void navigate (NavDirections directions)
public void navigate (NavDirections directions,
NavOptions navOptions)
public void navigate(@IdRes int resId, @Nullable Bundle args, @Nullable NavOptions navOptions,
@Nullable Navigator.Extras navigatorExtras)
private void navigate(@NonNull NavDestination node, @Nullable Bundle args,
@Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras)
public boolean navigateUp ()
返回到上⼀个页⾯
public boolean navigateUp (DrawerLayout drawerLayout)
public boolean navigateUp (AppConfiguration appConfiguration)
复制代码
resId 可以是NavXML中的action或者destination标签id, 如果是action则会附带action的选项, 如果是页⾯destination则不会附带destination标签下的⼦标签action(写了⽩写).
args 即需要在fragment之间传递的Bundle参数, 但是导航还⽀持另外⼀种插件形式的传递参数⽅式-安全参数SafeArgs, 后⾯提到. navOptions 即导航页⾯⼀些配置选项(例如动画)
navigatorExtras ⽬前是⽤于⽀持转场动画的共享元素.
ActivityNavigator和FragmentNavigator内部都实现了Navigator.Extras
通过扩展函数可以快速创建
fun FragmentNavigatorExtras(vararg sharedElements: Pair<View, String>) =
FragmentNavigator.Extras.Builder().apply {
sharedElements.forEach { (view, name) ->
安卓intent用法addSharedElement(view, name)
}
}.build()
fun ActivityNavigatorExtras(activityOptions: ActivityOptionsCompat? = null, flags: Int = 0) =
ActivityNavigator.Extras.Builder().apply {
if (activityOptions != null) {
setActivityOptions(activityOptions)
}
addFlags(flags)
}.build()
复制代码
可以从源码看到内部都是使⽤的Extras.Builder构造器创建的.
⽰例
<fragment
android:id="@+id/home_dest"
android:name="delabs.navigation.HomeFragment"
android:label="@string/home"
tools:layout="@layout/home_fragment">
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_one_dest"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
复制代码
上⾯你给action指定动画, 但是如果你使⽤的navigate中的参数resId不是_action⽽是R.id.home_dest. 那么你这个action相当于不⽣效.
弹出栈, 即从Nav回退栈中清除Fragment.
public boolean popBackStack (int destinationId, // ⽬标id
boolean inclusive) // 是否包含参数⽬标
public boolean popBackStack ()
弹出当前Fragment
复制代码
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论