项目中在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,升级。
完成后,果然: