Jetpack Navigation 页面管理

    技术2022-07-10  132

    项目中在Drawerlayout的抽屉中放入fragment作为Navigation的容器 用户按下返回键需要判断: 当前是S页或者是一级页面=》收起抽屉; 不是S页并且它不是二级页面=》返回上一页。 也就是说S页不是所有页面的起始页。 开始的时候只有几个页面,于是手动根据ID来控制。

    举个例子

    Navigation图如下: A B->C Navigation必须要有startDestination节点,随便设一个A。 当页面是A,返回键直接收起抽屉 当页面是B,返回键直接收起抽屉 当页面是C,返回键返回B

    治标不治本

    原始的手动控制

    when (nav.currentDestination) { nav.graph.findNode(R.id.changeNameFragment), nav.graph.findNode(R.id.discountCodeFragment), nav.graph.findNode(R.id.orderFragment) -> super.onBackPressed() nav.graph.findNode(R.id.shareFragment) -> { if (currentPage == 0) closeEndDrawer() else super.onBackPressed() } else -> closeEndDrawer() }

    差不多就这意思,当页面多了之后就开始烦了,比如上面的shareFragment,可能多个地方出现,这个地方它可能是二级页面,那个地方它可能是一级页面,不得不去解决这个问题。

    彻底解决

    Navigation其实就是一个栈控制的,supportFragmentManager.fragments中可以看见一个NavHostFragment 继续看

    发现: mBackStack[0]对应我们装Navigation的那个fragment

    <fragment android:id="@+id/nav_drawer_main" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_drawer_main" />

    mBackStack[1]对应我们app:navGraph中的startDestination mBackStack[2]对应我们当前显示的fragment

    再一次测试发现,即使调用

    nav.popBackStack(R.id.xxx,true)

    或者

    nav.Graph(R.navigation.xxx)

    来清除所有导航页面,然后直接跳转到我们需要的页面,这个startDestination还是会存在。

    所以现在返回键的判断逻辑就可以这么写。

    if(抽屉是展开的){ // 当前是起始页 || 上一页就是起始页 if(nav.currentDestination == startDestination页面对应的ID || mBackStack.size == 3){ closeDrawer()//收起抽屉 }else{ // Navigation默认处理返回键 super.onBackPressed() } }else{ 其他操作 }

    但是这个mBackStack是私有的获取不到,想了想会不会谷歌当时没考虑周全,也许后续升级会开放这个属性。 检查当前Navigation版本:2.2.2,最新版本:2.3.0,升级。

    完成后,果然:

    Processed: 0.015, SQL: 9