iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0

前言


Compose 中要在不同頁面之間切換,可以用 Navigation API。今天就來用在專案中

添加依賴


dependencies {
 implementation "androidx.navigation:navigation-compose:2.5.2"
}

NavController


NavController 是本次的主角,要創建他可以使用 rememberNavController 。這個 API 提供我們換頁的方法和有返回上頁的[currentBackStackEntryAsState()](https://developer.android.com/reference/kotlin/androidx/navigation/compose/package-summary#(androidx.navigation.NavController).currentBackStackEntryAsState())
 

val navController = rememberNavController()

頁面管家 NavHost


NavHost 就像是目錄,這裡會羅列出所有頁面的路徑。

NavHost 需要前面用 rememberNavController() 建立的 navController ,以及 startDestination 紀錄了起始頁面的路徑名稱。

最後一個參數 builder 可以在 lambda 內部使用 composable("rote"){} 來呈現一個頁面。

“rote” 是頁面路徑的名稱,而composable{} lambda 可以擺上之前做好的頁面 composable function。

val navController =rememberNavController()

NavHost(navController = navController, startDestination = "home"){
	composable("home"){
			MainScreen() //main page 的 composable function
	}
	composable("search"){
	
	}
	composable("training"){
	
	}

}

換到指定頁面


要換頁的話要用到 navControllernavigate() 裡面帶入要去頁面路徑名稱。

navController.navigate("search")

既然會很常用到路徑名稱,我就可以考慮把路徑提取出來作做成 enum 方便管理。

enum class NavPath {
    Main, Search, Training
}
val navController =rememberNavController()

NavHost(navController = navController, startDestination = NavPath.Main.name) {
    composable(NavPath.Main.name) { MainScreen() }
    composable(NavPath.Search.name) { SearchScreen() }
    composable(NavPath.Training.name) { TrainingScreen() }
}

在這個 APP 中有幾個跳轉路徑

MainScreen 可以跳轉到 SearchScreenTrainingScreen

SearchScreen 可以返回 MainScreen 或 進到搜尋結果的 TrainingScreen

TrainingScreen 則是可以回到上一頁。

舉 Main Screen 的參數例子

fun MainScreen(
    onSearchBarClick : () -> Unit,
    onAddTrainingClick : () -> Unit,
    onTrainingClick : () -> Unit,
) {
	//...
}

用在外 NavHost 就是這樣

NavHost(navController = navController, startDestination = NavPath.Main.name) {
    composable(NavPath.Main.name) {
        MainScreen(
            onSearchBarClick = { /*TODO*/ },
            onAddTrainingClick = { /*TODO*/ },
            onTrainingClick = { /*TODO*/ }
        )
    }
    composable(NavPath.Search.name) { SearchScreen() }
    composable(NavPath.Training.name) { TrainingScreen() }
}

接下來就可以在 onSearchBarClick 的 lambda 中執行換頁。

composable(NavPath.Main.name) {
    MainScreen(
        onSearchBarClick = { navController.navigate(NavPath.Search.name) },
        onAddTrainingClick = { navController.navigate(NavPath.Training.name)  },
        onTrainingClick = { navController.navigate(NavPath.Training.name)  }
    )
	//...
}

返回上一頁


要返回上一頁可以使用 navControllerpopBackStack()

navController.popBackStack()

首先在 SearchScreenTrainingScreen 新增 back 參數,用來傳遞回上一頁的 funtion

@Composable
fun SearchScreen(
    back: () -> Unit
) {
    //...
}

NavHost 使用時將 navController.popBackStack() 傳入 back lambda

NavHost(navController = navController, startDestination = NavPath.Main.name) {
    //...
    composable(NavPath.Search.name) { SearchScreen(back = { navController.popBackStack() }) }
    //...
}

總結


今天學會了 navigtion 的基本換頁功能,明天繼續探討 popup 和 換頁時要怎麼帶參數。

參考


Navigating with Compose

今日運動
深蹲
40kg 15 15 15
50kg 10 8 12
45kg 8 8 8
槓鈴肩推
15kg 12 8 8 8
(熬夜 使人體力退步)


上一篇
Day 20 使用三方庫做出 LazyGrid 拖曳排序
下一篇
Day 22 navigation popup & paramater
系列文
今年一定減成功!Jetpack Compose 做出重訓紀錄APP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言