@@ -3,24 +3,29 @@ package dev.johnoreilly.mortycomposekmm.ui
33import android.os.Bundle
44import androidx.activity.ComponentActivity
55import androidx.activity.compose.setContent
6+ import androidx.activity.enableEdgeToEdge
67import androidx.compose.foundation.layout.fillMaxSize
78import androidx.compose.foundation.layout.padding
8- import androidx.compose.material.*
99import androidx.compose.material.icons.Icons
1010import androidx.compose.material.icons.filled.LocationOn
1111import androidx.compose.material.icons.filled.Person
1212import androidx.compose.material.icons.filled.Tv
13+ import androidx.compose.material3.*
1314import androidx.compose.runtime.*
1415import androidx.compose.ui.Modifier
1516import androidx.compose.ui.graphics.vector.ImageVector
17+ import androidx.compose.ui.unit.dp
1618import androidx.navigation.NavHostController
1719import androidx.navigation.compose.*
1820import dev.johnoreilly.mortycomposekmm.ui.characters.CharacterDetailView
1921import dev.johnoreilly.mortycomposekmm.ui.characters.CharactersListView
22+ import dev.johnoreilly.mortycomposekmm.ui.components.MortyTopAppBar
23+ import dev.johnoreilly.mortycomposekmm.ui.components.MortyDetailTopAppBar
2024import dev.johnoreilly.mortycomposekmm.ui.episodes.EpisodeDetailView
2125import dev.johnoreilly.mortycomposekmm.ui.episodes.EpisodesListView
2226import dev.johnoreilly.mortycomposekmm.ui.locations.LocationDetailView
2327import dev.johnoreilly.mortycomposekmm.ui.locations.LocationsListView
28+ import dev.johnoreilly.mortycomposekmm.ui.theme.MortyComposeTheme
2429
2530
2631sealed class Screens (val route : String , val label : String , val icon : ImageVector ? = null ) {
@@ -37,35 +42,89 @@ class MainActivity : ComponentActivity() {
3742 override fun onCreate (savedInstanceState : Bundle ? ) {
3843 super .onCreate(savedInstanceState)
3944
45+ enableEdgeToEdge()
4046 setContent {
41- MaterialTheme {
47+ MortyComposeTheme {
4248 MainLayout ()
4349 }
4450 }
4551 }
4652}
4753
54+ @OptIn(ExperimentalMaterial3Api ::class )
4855@Composable
4956fun MainLayout () {
5057 val navController = rememberNavController()
58+ val currentRoute = currentRoute(navController)
59+
60+ // State to hold the detail screen title
61+ var detailTitle by remember { mutableStateOf(" " ) }
62+
63+ // Function to update the detail title (will be passed to detail screens)
64+ val updateDetailTitle: (String ) -> Unit = { title ->
65+ detailTitle = title
66+ }
67+
68+ // Determine if we're on a detail screen
69+ val isDetailScreen = remember(currentRoute) {
70+ currentRoute?.startsWith(Screens .CharacterDetailsScreen .route) == true ||
71+ currentRoute?.startsWith(Screens .EpisodeDetailsScreen .route) == true ||
72+ currentRoute?.startsWith(Screens .LocationDetailsScreen .route) == true
73+ }
74+
75+ // Get current main screen based on route
76+ val currentMainScreen = remember(currentRoute) {
77+ when (currentRoute) {
78+ Screens .CharactersScreen .route -> Screens .CharactersScreen
79+ Screens .EpisodesScreen .route -> Screens .EpisodesScreen
80+ Screens .LocationsScreen .route -> Screens .LocationsScreen
81+ else -> Screens .CharactersScreen
82+ }
83+ }
5184
5285 val bottomNavigationItems = listOf (Screens .CharactersScreen , Screens .EpisodesScreen , Screens .LocationsScreen )
5386
5487 Scaffold (
55- topBar = { TopAppBar (title = { Text ( " Characters" ) }) },
56- bottomBar = { MortyBottomNavigation (navController, bottomNavigationItems) })
57- {
88+ // Use our shared MortyTopAppBar component with dynamic content
89+ topBar = {
90+ if (isDetailScreen) {
91+ // Use detail app bar for detail screens
92+ MortyDetailTopAppBar (
93+ title = detailTitle,
94+ onBackClick = { navController.popBackStack() }
95+ )
96+ } else {
97+ // Use regular app bar for main screens
98+ MortyTopAppBar (
99+ title = currentMainScreen.label
100+ )
101+ }
102+ },
103+ // Apply navigation bar padding to the bottom navigation
104+ bottomBar = {
105+ Surface (
106+ tonalElevation = 8 .dp,
107+ color = MaterialTheme .colorScheme.surface,
108+ ) {
109+ MortyBottomNavigation (navController, bottomNavigationItems)
110+ }
111+ },
112+ containerColor = MaterialTheme .colorScheme.background
113+ ) { paddingValues ->
58114
59- NavHost (navController, startDestination = Screens .CharactersScreen .route, modifier = Modifier .padding(it).fillMaxSize()) {
115+ NavHost (navController, startDestination = Screens .CharactersScreen .route,
116+ modifier = Modifier .padding(paddingValues).fillMaxSize()) {
60117 composable(Screens .CharactersScreen .route) {
61118 CharactersListView () {
62119 navController.navigate(Screens .CharacterDetailsScreen .route + " /${it.id} " )
63120 }
64121 }
65122 composable(Screens .CharacterDetailsScreen .route + " /{id}" ) { backStackEntry ->
66123 CharacterDetailView (
67- backStackEntry.arguments?.getString(" id" ) as String ,
68- popBack = { navController.popBackStack() })
124+ characterId = backStackEntry.arguments?.getString(" id" ) as String ,
125+ popBack = { navController.popBackStack() },
126+ updateTitle = updateDetailTitle
127+ )
69128 }
70129 composable(Screens .EpisodesScreen .route) {
71130 EpisodesListView () {
@@ -74,8 +133,10 @@ fun MainLayout() {
74133 }
75134 composable(Screens .EpisodeDetailsScreen .route + " /{id}" ) { backStackEntry ->
76135 EpisodeDetailView (
77- backStackEntry.arguments?.getString(" id" ) as String ,
78- popBack = { navController.popBackStack() })
136+ episodeId = backStackEntry.arguments?.getString(" id" ) as String ,
137+ popBack = { navController.popBackStack() },
138+ updateTitle = updateDetailTitle
139+ )
79140 }
80141 composable(Screens .LocationsScreen .route) {
81142 LocationsListView () {
@@ -84,8 +145,10 @@ fun MainLayout() {
84145 }
85146 composable(Screens .LocationDetailsScreen .route + " /{id}" ) { backStackEntry ->
86147 LocationDetailView (
87- backStackEntry.arguments?.getString(" id" ) as String ,
88- popBack = { navController.popBackStack() })
148+ locationId = backStackEntry.arguments?.getString(" id" ) as String ,
149+ popBack = { navController.popBackStack() },
150+ updateTitle = updateDetailTitle
151+ )
89152 }
90153 }
91154 }
@@ -97,10 +160,10 @@ private fun MortyBottomNavigation(
97160 navController : NavHostController ,
98161 items : List <Screens >
99162) {
100- BottomNavigation {
163+ NavigationBar {
101164 val currentRoute = currentRoute(navController)
102165 items.forEach { screen ->
103- BottomNavigationItem (
166+ NavigationBarItem (
104167 icon = { screen.icon?.let { Icon (screen.icon, contentDescription = screen.label) } },
105168 label = { Text (screen.label) },
106169 selected = currentRoute == screen.route,
@@ -115,12 +178,10 @@ private fun MortyBottomNavigation(
115178 )
116179 }
117180 }
118-
119181}
120182
121183@Composable
122184private fun currentRoute (navController : NavHostController ): String? {
123185 val navBackStackEntry by navController.currentBackStackEntryAsState()
124186 return navBackStackEntry?.destination?.route
125- }
126-
187+ }
0 commit comments