Jetpack Composeのnavigation routeにURLを含めるときは、URLEncodeする必要がある
- 失敗するコード ・NavigationGraph
@Composable fun MainNavGraph( navController: NavHostController, modifier: Modifier = Modifier ){ NavHost( navController = navController, startDestination = Screen.Home.route, modifier = modifier ){ // このrouteにnavigateしたい composable( route = "${Screen.EpisodeDetail.route}/" + "{" + Constants.nav_episodeName + "}/" + "{" + Constants.nav_imageUrl + "}/" + "{" + Constants.nav_description + "}/" + "{" + Constants.nav_duration + "}/" + "{" + Constants.nav_releaseDate + "}", arguments = listOf( navArgument(Constants.nav_episodeName){ type = NavType.StringType }, navArgument(Constants.nav_imageUrl){ type = NavType.StringType }, navArgument(Constants.nav_description){ type = NavType.StringType }, navArgument(Constants.nav_duration){ type = NavType.IntType }, navArgument(Constants.nav_releaseDate){ type = NavType.StringType }, ) ){ navBackStackEntry -> val episodeName = navBackStackEntry.arguments?.getString(Constants.nav_episodeName) val imageUrl = navBackStackEntry.arguments?.getString(Constants.nav_imageUrl) val description = navBackStackEntry.arguments?.getString(Constants.nav_description) val duration = navBackStackEntry.arguments?.getInt(Constants.nav_duration) val releaseDate = navBackStackEntry.arguments?.getString(Constants.nav_releaseDate) EpisodeDetailScreen( episodeName = episodeName!!, imageUrl = imageUrl!!, description = description!!, duration = duration!!, releaseDate = releaseDate!! ) } } }
・遷移
@Composable fun EpisodesScreen( navController: NavController, showId: String? ) { val viewModel: EpisodesScreenViewModel = hiltViewModel() // Hold the Show ID for this screen. // TODO: Needs better code here. viewModel.showId = showId val lazyPagingItems = viewModel.pagingFlow.collectAsLazyPagingItems() val isRefreshing by viewModel.isRefreshing.collectAsState() SwipeRefresh( state = rememberSwipeRefreshState(isRefreshing), onRefresh = { lazyPagingItems.refresh() } ) { Column { Text(text = "Episodes") Text(text = lazyPagingItems.itemCount.toString()) LazyColumn { items(lazyPagingItems) { episodeItem -> EpisodeCardSquare( episodeName = episodeItem!!.name, imageUrl = episodeItem!!.images[2].url, description = episodeItem!!.description, duration = episodeItem!!.duration_ms, releaseDate = episodeItem!!.release_date, // Navigate to episode-detail screen. onClick = { navController.navigate( "${Screen.EpisodeDetail.route}/" + "${episodeItem!!.name}/" + "${episodeItem!!.images[2].url}/" + "${episodeItem!!.description}/" + "${episodeItem!!.duration_ms}/" + "${episodeItem!!.release_date}" ) } ) } } } } }
- 修正後コード ・NavigationGraphは変更なし ・遷移元
@Composable fun EpisodesScreen( navController: NavController, showId: String? ) { val viewModel: EpisodesScreenViewModel = hiltViewModel() // Hold the Show ID for this screen. // TODO: Needs better code here. viewModel.showId = showId val lazyPagingItems = viewModel.pagingFlow.collectAsLazyPagingItems() val isRefreshing by viewModel.isRefreshing.collectAsState() SwipeRefresh( state = rememberSwipeRefreshState(isRefreshing), onRefresh = { lazyPagingItems.refresh() } ) { Column { Text(text = "Episodes") Text(text = lazyPagingItems.itemCount.toString()) LazyColumn { items(lazyPagingItems) { episodeItem -> EpisodeCardSquare( episodeName = episodeItem!!.name, imageUrl = episodeItem!!.images[2].url, description = episodeItem!!.description, duration = episodeItem!!.duration_ms, releaseDate = episodeItem!!.release_date, // Navigate to episode-detail screen. onClick = { // URLが含まれる情報をURLEncodeしてから、navController.navitateに渡す。 val encodedImageUrl = URLEncoder.encode(episodeItem!!.images[2].url, StandardCharsets.UTF_8.toString()) val encodedDescription = URLEncoder.encode(episodeItem!!.description, StandardCharsets.UTF_8.toString()) navController.navigate( "${Screen.EpisodeDetail.route}/" + "${episodeItem!!.name}/" + "${encodedImageUrl}/" + "${encodedDescription}/" + "${episodeItem!!.duration_ms}/" + "${episodeItem!!.release_date}" ) } ) } } } } }