歡迎來到第二個關於導航的 MAD Skill 系列 的另一篇文章!本文我們將介紹一個呼聲很高的功能,即導航 (Navigation) 對多返回棧的支援。如果您更傾向於視訊的形式,請 點選這裡 檢視視訊內容。
概述
假設您的應用使用了 BottomNavigationView
。通過這個功能,當使用者選擇另一個標籤頁 (Tab) 時,當前標籤頁的返回棧會被儲存,而所選標籤頁的返回棧會被恢復。
從 2.4.0-alpha01 版本開始,NavigationUI
輔助類不需要改變任何程式碼即可支援多返回棧。也就是說,如果您的應用使用了為 BottomNavigationView
或 NavigationView
提供的 setupWithNavController()
方法,則只需要更新依賴庫版本,便可預設啟用多返回棧。
支援多返回棧
讓我們通過這個 倉庫 中的高階導航示例來看看實際效果。
該應用由 3 個標籤頁組成,每個標籤頁都有它自己的導航流。為了在導航的早期版本中支援多返回棧,我們需要在該示例的 NavigationExtensions 檔案中新增一系列輔助函式。通過這些擴充套件函式,應用可以為每個標籤頁保持一個單獨的 NavHostFragment
,每個 NavHostFragment
帶有它自己的返回棧,當使用者切換標籤頁時,應用在不同的 NavHostFragment
之間進行切換。
讓我們看看如果移除這些擴充套件函式會發生什麼。為此我刪除了 NavigationExtensions
類,在所有使用它的地方都替換為 NavigationUI
中標準的 setupWithNavController()
方法以將我們的 BottomNavigationView
連線到 NavController
上。
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController
// 使用 navController 設定 bottomNavigationView
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)
// 使用 navController 設定 ActionBar 以及 3 個一級目的地頁面
appBarConfiguration = AppBarConfiguration(
setOf(R.id.titleScreen, R.id.leaderboard, R.id.register)
)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
toolbar.setupWithNavController(navController, appBarConfiguration)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration)
}
}
同時,我使用 include
標籤將 3 個單獨的導航圖合併為一個圖。現在我們的 Activity 佈局只包含一個帶有單個導航圖的 NavHostFragment
。
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/home">
<include app:graph="@navigation/home"/>
<include app:graph="@navigation/list"/>
<include app:graph="@navigation/form"/>
</navigation>
當我執行應用時,這次底部標籤頁不再保持它們的狀態,並會在我切換到其他標籤頁時重置它的返回棧。由於移除了 NavigationExtensions
,該應用不再支援多返回棧。
現在我將更新 navigation 和 fragment 依賴庫的版本。
// fragment 最新版本 https://developer.android.google.cn/jetpack/androidx/releases/fragment?hl=en
// navigation 最新版本 https://developer.android.google.cn/jetpack/androidx/releases/navigation?hl=en
versions.fragment = "1.4.0-alphaXXX"
versions.navigation = "2.4.0-alphaXXX"
Gradle sync 完成後,我再次執行應用,這時當我導航至其他標籤頁,可以看到每個標籤頁都保持了它的狀態。注意這個行為是預設啟用的。
最後,讓我們執行測試來驗證是否一切正常。該應用已經擁有一些驗證多返回棧行為的測試。我執行 BottomNavigationTest 並觀察每個底部導航行為測試的執行。
瞧,我們所有測試都通過了!
小結
就是這樣!如果您的應用使用 BottomNavigationView
或 NavigationView
,並且您一直在等待支援多返回棧,您所需要做的僅僅是更新 navigation 和 fragment 依賴庫,不需要改變任何程式碼!
如果您需要進一步的自定義,也有新的 API 支援儲存和恢復返回棧。請參閱我們之前的推文《Android 多返回棧技術詳解》。
如果您想了解更多有關底層 API 以及需要修改哪些內容以支援多返回棧的資訊,請參閱我們之前的推文《全新的 Fragment: 使用新的狀態管理器》。
感謝您關注本導航系列!
歡迎您 點選這裡 向我們提交反饋,或分享您喜歡的內容、發現的問題。您的反饋對我們非常重要,感謝您的支援!