隨著功能越來越多,畫面也會越來越多,跳轉畫面與返回也逐漸複雜,所以會使用 Navigation 函式庫統一處理畫面轉換與返回操作,也降低畫面之間的依賴關係。
官方文件:
https://developer.android.com/jetpack/compose/navigation
多個 Destination 組成 NavGraph,NavHostController 負責控制畫面轉換與返回操作。
每個畫面被稱為 destination,每個 destination 都要設定一個 route 字串,之後控制時就是用 route 字串決定要導向到哪個頁面。
NavGraph 顧名思義它是一張有向圖(圖學的 graph,不是圖片的 image)。
@Composable
fun MainView() {
val controller = rememberNavController()
NavHost(
navController = controller,
startDestination = "home"
) {
composable("home") { HomeScreen(controller) }
composable("setting") { SettingScreen() }
}
}
@Composable
fun HomeScreen(controller: NavHostController) {
Button(onClick = {
controller.navigate("setting")
}) {
Text("To setting")
}
}
@Composable
fun SettingScreen() {
Text("Setting")
}
GitHub:
https://github.com/raamcosta/compose-destinations
基於官方 Navigation 函式庫,但它多了程式碼生成器與一些標注,開發者只要在畫面的 composable function 加上標注,它就會生出對應的 NavGraph 與 Destination 物件。
@RootNavGraph(start = true)
@Destination
@Composable
fun HomeScreen(controller: NavHostController) {
Button(onClick = {
controller.navigate("setting")
}) {
Text("To setting")
}
}
@Destination
@Composable
fun SettingScreen() {
Text("Setting")
}
相較於官方的優點是型別安全,判斷跳轉的 destination 是物件而不是字串,而且生成的 destination 物件是 sealed class,可以用 when
獲取 destination 對應的自訂物件。
fun Destination.toMyRoute(): MyRoute = when (this) {
HomeScreenDestination -> MyRoute.Home
SettingScreenDestination -> MyRoute.Setting
}
GitHub:
https://github.com/adrielcafe/voyager
Voyager 是一個多平台 Compose Navigation 函式庫,因為是多平台的關係,所以不依賴 Android Lifecycle,以 Screen 物件取代 route 字串達成型別安全,不過最後的 commit 跟 release 停留在 5 月,代表這個專案已經不太活躍,所以後來我改用 Compose Destinations。
@Composable
fun MainView() {
Navigator(HomeScreen) {
CurrentScreen()
}
}
object HomeScreen : Screen {
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
Button(onClick = {
navigator.push(SettingScreen)
}) {
Text("To setting")
}
}
}
object SettingScreen : Screen {
@Composable
override fun Content() {
Text("Setting")
}
}