Jetpack Navigation 頁面管理

項目中在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
NavHostFragment
繼續看
mBackStack

發現:
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,升級。

完成後,果然:
屬性出來了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章