@@ -3,24 +3,29 @@ package dev.johnoreilly.mortycomposekmm.ui
3
3
import android.os.Bundle
4
4
import androidx.activity.ComponentActivity
5
5
import androidx.activity.compose.setContent
6
+ import androidx.activity.enableEdgeToEdge
6
7
import androidx.compose.foundation.layout.fillMaxSize
7
8
import androidx.compose.foundation.layout.padding
8
- import androidx.compose.material.*
9
9
import androidx.compose.material.icons.Icons
10
10
import androidx.compose.material.icons.filled.LocationOn
11
11
import androidx.compose.material.icons.filled.Person
12
12
import androidx.compose.material.icons.filled.Tv
13
+ import androidx.compose.material3.*
13
14
import androidx.compose.runtime.*
14
15
import androidx.compose.ui.Modifier
15
16
import androidx.compose.ui.graphics.vector.ImageVector
17
+ import androidx.compose.ui.unit.dp
16
18
import androidx.navigation.NavHostController
17
19
import androidx.navigation.compose.*
18
20
import dev.johnoreilly.mortycomposekmm.ui.characters.CharacterDetailView
19
21
import dev.johnoreilly.mortycomposekmm.ui.characters.CharactersListView
22
+ import dev.johnoreilly.mortycomposekmm.ui.components.MortyTopAppBar
23
+ import dev.johnoreilly.mortycomposekmm.ui.components.MortyDetailTopAppBar
20
24
import dev.johnoreilly.mortycomposekmm.ui.episodes.EpisodeDetailView
21
25
import dev.johnoreilly.mortycomposekmm.ui.episodes.EpisodesListView
22
26
import dev.johnoreilly.mortycomposekmm.ui.locations.LocationDetailView
23
27
import dev.johnoreilly.mortycomposekmm.ui.locations.LocationsListView
28
+ import dev.johnoreilly.mortycomposekmm.ui.theme.MortyComposeTheme
24
29
25
30
26
31
sealed class Screens (val route : String , val label : String , val icon : ImageVector ? = null ) {
@@ -37,35 +42,89 @@ class MainActivity : ComponentActivity() {
37
42
override fun onCreate (savedInstanceState : Bundle ? ) {
38
43
super .onCreate(savedInstanceState)
39
44
45
+ enableEdgeToEdge()
40
46
setContent {
41
- MaterialTheme {
47
+ MortyComposeTheme {
42
48
MainLayout ()
43
49
}
44
50
}
45
51
}
46
52
}
47
53
54
+ @OptIn(ExperimentalMaterial3Api ::class )
48
55
@Composable
49
56
fun MainLayout () {
50
57
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
+ }
51
84
52
85
val bottomNavigationItems = listOf (Screens .CharactersScreen , Screens .EpisodesScreen , Screens .LocationsScreen )
53
86
54
87
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 ->
58
114
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()) {
60
117
composable(Screens .CharactersScreen .route) {
61
118
CharactersListView () {
62
119
navController.navigate(Screens .CharacterDetailsScreen .route + " /${it.id} " )
63
120
}
64
121
}
65
122
composable(Screens .CharacterDetailsScreen .route + " /{id}" ) { backStackEntry ->
66
123
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
+ )
69
128
}
70
129
composable(Screens .EpisodesScreen .route) {
71
130
EpisodesListView () {
@@ -74,8 +133,10 @@ fun MainLayout() {
74
133
}
75
134
composable(Screens .EpisodeDetailsScreen .route + " /{id}" ) { backStackEntry ->
76
135
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
+ )
79
140
}
80
141
composable(Screens .LocationsScreen .route) {
81
142
LocationsListView () {
@@ -84,8 +145,10 @@ fun MainLayout() {
84
145
}
85
146
composable(Screens .LocationDetailsScreen .route + " /{id}" ) { backStackEntry ->
86
147
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
+ )
89
152
}
90
153
}
91
154
}
@@ -97,10 +160,10 @@ private fun MortyBottomNavigation(
97
160
navController : NavHostController ,
98
161
items : List <Screens >
99
162
) {
100
- BottomNavigation {
163
+ NavigationBar {
101
164
val currentRoute = currentRoute(navController)
102
165
items.forEach { screen ->
103
- BottomNavigationItem (
166
+ NavigationBarItem (
104
167
icon = { screen.icon?.let { Icon (screen.icon, contentDescription = screen.label) } },
105
168
label = { Text (screen.label) },
106
169
selected = currentRoute == screen.route,
@@ -115,12 +178,10 @@ private fun MortyBottomNavigation(
115
178
)
116
179
}
117
180
}
118
-
119
181
}
120
182
121
183
@Composable
122
184
private fun currentRoute (navController : NavHostController ): String? {
123
185
val navBackStackEntry by navController.currentBackStackEntryAsState()
124
186
return navBackStackEntry?.destination?.route
125
- }
126
-
187
+ }
0 commit comments