@@ -11,44 +11,46 @@ import androidx.compose.material.icons.Icons
1111import androidx.compose.material.icons.filled.Home
1212import androidx.compose.material.icons.filled.Menu
1313import androidx.compose.material.icons.filled.Person
14- import androidx.compose.material.icons.filled.Search
1514import androidx.compose.material3.Icon
1615import androidx.compose.material3.NavigationBar
1716import androidx.compose.material3.NavigationBarItem
1817import androidx.compose.material3.Scaffold
1918import androidx.compose.material3.Text
2019import androidx.compose.runtime.getValue
2120import androidx.compose.ui.Modifier
21+ import androidx.compose.ui.graphics.vector.ImageVector
2222import androidx.compose.ui.res.stringResource
23- import androidx.compose.ui.unit.dp
24- import androidx.navigation.NavDestination
23+ import androidx.navigation.NavDestination.Companion.hasRoute
2524import androidx.navigation.NavDestination.Companion.hierarchy
26- import androidx.navigation.NavGraph.Companion.findStartDestination
2725import androidx.navigation.compose.NavHost
26+ import androidx.navigation.compose.composable
2827import androidx.navigation.compose.currentBackStackEntryAsState
2928import androidx.navigation.compose.rememberNavController
3029import com.google.firebase.dataconnect.movies.MoviesConnector
3130import com.google.firebase.dataconnect.movies.instance
32- import com.google.firebase.example.dataconnect.feature.actordetail.actorDetailScreen
33- import com.google.firebase.example.dataconnect.feature.actordetail.navigateToActorDetail
34- import com.google.firebase.example.dataconnect.feature.genredetail.genreDetailScreen
35- import com.google.firebase.example.dataconnect.feature.genredetail.navigateToGenreDetail
36- import com.google.firebase.example.dataconnect.feature.genres.GENRES_ROUTE
37- import com.google.firebase.example.dataconnect.feature.genres.genresScreen
38- import com.google.firebase.example.dataconnect.feature.genres.navigateToGenres
39- import com.google.firebase.example.dataconnect.feature.moviedetail.movieDetailScreen
40- import com.google.firebase.example.dataconnect.feature.moviedetail.navigateToMovieDetail
41- import com.google.firebase.example.dataconnect.feature.movies.MOVIES_ROUTE
42- import com.google.firebase.example.dataconnect.feature.movies.moviesScreen
43- import com.google.firebase.example.dataconnect.feature.movies.navigateToMovies
44- import com.google.firebase.example.dataconnect.feature.profile.PROFILE_ROUTE
45- import com.google.firebase.example.dataconnect.feature.profile.navigateToProfile
46- import com.google.firebase.example.dataconnect.feature.profile.profileScreen
47- import com.google.firebase.example.dataconnect.feature.search.SEARCH_ROUTE
48- import com.google.firebase.example.dataconnect.feature.search.navigateToSearch
31+ import com.google.firebase.example.dataconnect.feature.actordetail.ActorDetailRoute
32+ import com.google.firebase.example.dataconnect.feature.actordetail.ActorDetailScreen
33+ import com.google.firebase.example.dataconnect.feature.genredetail.GenreDetailRoute
34+ import com.google.firebase.example.dataconnect.feature.genredetail.GenreDetailScreen
35+ import com.google.firebase.example.dataconnect.feature.genres.GenresRoute
36+ import com.google.firebase.example.dataconnect.feature.genres.GenresScreen
37+ import com.google.firebase.example.dataconnect.feature.moviedetail.MovieDetailRoute
38+ import com.google.firebase.example.dataconnect.feature.moviedetail.MovieDetailScreen
39+ import com.google.firebase.example.dataconnect.feature.movies.MoviesRoute
40+ import com.google.firebase.example.dataconnect.feature.movies.MoviesScreen
41+ import com.google.firebase.example.dataconnect.feature.profile.ProfileRoute
42+ import com.google.firebase.example.dataconnect.feature.profile.ProfileScreen
4943import com.google.firebase.example.dataconnect.feature.search.searchScreen
5044import com.google.firebase.example.dataconnect.ui.theme.FirebaseDataConnectTheme
5145
46+ data class TopLevelRoute <T : Any >(val labelResId : Int , val route : T , val icon : ImageVector )
47+
48+ val TOP_LEVEL_ROUTES = listOf (
49+ TopLevelRoute (R .string.label_movies, MoviesRoute , Icons .Filled .Home ),
50+ TopLevelRoute (R .string.label_genres, GenresRoute , Icons .Filled .Menu ),
51+ TopLevelRoute (R .string.label_profile, ProfileRoute , Icons .Filled .Person )
52+ )
53+
5254class MainActivity : ComponentActivity () {
5355 override fun onCreate (savedInstanceState : Bundle ? ) {
5456 super .onCreate(savedInstanceState)
@@ -64,75 +66,70 @@ class MainActivity : ComponentActivity() {
6466 NavigationBar {
6567 val navBackStackEntry by navController.currentBackStackEntryAsState()
6668 val currentDestination = navBackStackEntry?.destination
67- NavigationBarItem (
68- icon = { Icon (Icons .Filled .Home , contentDescription = null ) },
69- label = { Text (stringResource(R .string.label_movies)) },
70- selected = isRouteSelected(currentDestination, MOVIES_ROUTE ),
71- onClick = {
72- navController.navigateToMovies { launchSingleTop = true }
73- }
74- )
75- NavigationBarItem (
76- icon = { Icon (Icons .Filled .Menu , contentDescription = null ) },
77- label = { Text (stringResource(R .string.label_genres)) },
78- selected = isRouteSelected(currentDestination, GENRES_ROUTE ),
79- onClick = {
80- navController.navigateToGenres { launchSingleTop = true }
81- }
82- )
83- NavigationBarItem (
84- icon = { Icon (Icons .Filled .Search , contentDescription = null ) },
85- label = { Text (stringResource(R .string.label_search)) },
86- selected = isRouteSelected(currentDestination, SEARCH_ROUTE ),
87- onClick = {
88- navController.navigateToSearch { launchSingleTop = true }
89- }
90- )
91- NavigationBarItem (
92- icon = { Icon (Icons .Filled .Person , contentDescription = null ) },
93- label = { Text (stringResource(R .string.label_profile)) },
94- selected = isRouteSelected(currentDestination, PROFILE_ROUTE ),
95- onClick = {
96- navController.navigateToProfile { launchSingleTop = true }
97- }
98- )
69+
70+ TOP_LEVEL_ROUTES .forEach { topLevelRoute ->
71+ val label = stringResource(topLevelRoute.labelResId)
72+ NavigationBarItem (
73+ icon = { Icon (topLevelRoute.icon, contentDescription = label) },
74+ label = { Text (label) },
75+ selected = currentDestination?.hierarchy?.any {
76+ it.hasRoute(topLevelRoute.route::class )
77+ } == true ,
78+ onClick = {
79+ navController.navigate(
80+ topLevelRoute.route,
81+ { launchSingleTop = true }
82+ )
83+ }
84+ )
85+ }
9986 }
10087 }
10188 ) { innerPadding ->
10289 NavHost (
10390 navController,
104- startDestination = MOVIES_ROUTE ,
91+ startDestination = MoviesRoute ,
10592 Modifier
10693 .padding(innerPadding)
10794 .consumeWindowInsets(innerPadding),
10895 ) {
109- moviesScreen(onMovieClicked = { movieId ->
110- navController.navigateToMovieDetail(movieId) {
111- launchSingleTop = true
112- }
113- })
114- movieDetailScreen(
115- onActorClicked = { actorId ->
116- navController.navigateToActorDetail(actorId) {
117- launchSingleTop = true
96+ composable< MoviesRoute >() {
97+ MoviesScreen (
98+ onMovieClicked = { movieId ->
99+ navController.navigate(
100+ route = MovieDetailRoute (movieId),
101+ builder = {
102+ launchSingleTop = true
103+ }
104+ )
118105 }
119- }
120- )
121- actorDetailScreen()
122- genresScreen(onGenreClicked = { genre ->
123- navController.navigateToGenreDetail(genre) {
124- launchSingleTop = true
125- }
126- })
127- genreDetailScreen()
106+ )
107+ }
108+ composable<MovieDetailRoute > {
109+ MovieDetailScreen (
110+ onActorClicked = { actorId ->
111+ navController.navigate(
112+ ActorDetailRoute (actorId),
113+ { launchSingleTop = true }
114+ )
115+ }
116+ )
117+ }
118+ composable<ActorDetailRoute >() { ActorDetailScreen () }
119+ composable<GenresRoute > {
120+ GenresScreen (onGenreClicked = { genre ->
121+ navController.navigate(
122+ GenreDetailRoute (genre),
123+ { launchSingleTop = true }
124+ )
125+ })
126+ }
127+ composable<GenreDetailRoute > { GenreDetailScreen () }
128128 searchScreen()
129- profileScreen()
129+ composable< ProfileRoute > { ProfileScreen () }
130130 }
131131 }
132132 }
133133 }
134134 }
135135}
136-
137- private fun isRouteSelected (currentDestination : NavDestination ? , route : String ) =
138- currentDestination?.hierarchy?.any { it.route?.startsWith(route) ? : false } == true
0 commit comments