今回実装する機能
観光地リストから観光地の詳細情報が載っている詳細画面に移動する機能です。
XML は一切使わずに全てjetpack compose で画面も実装します。
必要なもの
今回はいくつかのプログラムファイルに分けて実装しています。
- NavController の宣言
- NavHost で遷移する画面の宣言
- 引数のタイプをあらかじめ宣言
- クリック時の処理に詳細画面のルートを指定して遷移するようにする
プログラムの動作
今回のアプリはこのような動作をします。
mermaid により図を作成
プログラムの構成
アプリは以下のような構成で成り立っています。
mermaid により図を作成
Activity
MainActivity.kt
// 今回はviewModelを使用します。
private val LandmarkViewModel: LandmarkViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
JetpackListTheme {
Surface {
//navController を引数として view セットメソッドに渡します。
val navController = rememberNavController()
SetLandmarkView(LandmarkViewModel,navController = navController)
}
}
}
}
画面名 enum class
screen.kt
// これは画面の名前を設定して遷移するために使用します
enum class Screen {
LANDMARKS,
LANDMARK_DETAIL
}
リスト表示部
LandmarkList.kt
@Composable
fun SetLandmarkView(landmarkViewModel: LandmarkViewModel,navController: NavHostController){
// NavController から NavHost を設定します
// startDestination で最初に表示する画面を決定します。
NavHost(navController = navController, startDestination = Screen.LANDMARKS.name) {
// 観光地リストを表示する画面
// リストせるをクリックしたときに詳細画面への遷移のためにnavController を渡しておきます
composable(Screen.LANDMARKS.name) {
LandmarkList(viewModel = landmarkViewModel,navController)
}
// 詳細画面を表示する
// 表示するための id を設定する
composable("${Screen.LANDMARK_DETAIL.name}/{landmarkId}/{landmarkName}/{description}/{airport}",
// 引数はここでどんなタイプのものを使用するのかを宣言する必要あり
arguments = listOf(
navArgument("landmarkId") {type = NavType.IntType},
navArgument("landmarkName") {type = NavType.StringType},
navArgument("description"){type = NavType.StringType},
navArgument("airport"){type = NavType.StringType},
)
)
{ backStackEntry ->
val landmarkId = backStackEntry.arguments?.getInt("landmarkId") ?: 0
val landmarkName = backStackEntry.arguments?.getString("landmarkName") ?: ""
val description = backStackEntry.arguments?.getString("description") ?: ""
val airport = backStackEntry.arguments?.getString("airport") ?: ""
LandmarkDetailView(
landmarkId=landmarkId,
landmarkName=landmarkName,
description=description,
airport=airport
)
}
}
}
リスト部品部
LandmarkList.kt
@Composable
fun ListItem(landmark: LandmarkData,navController: NavController) {
Column(modifier = Modifier
.fillMaxWidth()
// クリックしたときに画面遷移するように 詳細画面の id を指定する
.clickable {
navController.navigate("${Screen.LANDMARK_DETAIL.name}/${landmark.id}/${landmark.name}/${landmark.description}/${landmark.airport}")
}
//...
}
引数の関係
NavHost にて定義した引数は以下のように対応します。
観光地リストを表示する composable 関数
LandmarkList.kt
NavHost(navController = navController, startDestination = Screen.LANDMARKS.name){
composable(Screen.LANDMARKS.name) {
LandmarkList(viewModel = landmarkViewModel,navController)
}
}
LandmarkList.kt
@Composable
fun LandmarkList(viewModel: LandmarkViewModel,navController: NavController)
観光地詳細情報を表示する composable 関数
LandmarkList.kt
composable("${Screen.LANDMARK_DETAIL.name}/{landmarkId}/{landmarkName}/{description}/{airport}",
arguments = listOf(
navArgument("landmarkId") {type = NavType.IntType},
navArgument("landmarkName") {type = NavType.StringType},
navArgument("description"){type = NavType.StringType},
navArgument("airport"){type = NavType.StringType},
)
)
LandmarkList.kt
@Composable
fun LandmarkDetailView(landmarkId: Int,landmarkName: String,description:String,airport:String)
このようにすれば、 Jetpack Compose で実装した画面間を移動できるはずです。