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