Navigation
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/com/vocabri/ui/navigation/AppNavigation.kt
- app/src/main/java/com/vocabri/ui/navigation/NavigationRoute.kt
- app/src/main/java/com/vocabri/ui/navigation/MainBottomNavigation.kt
- app/src/main/java/com/vocabri/ui/main/MainScreen.kt
- app/src/main/java/com/vocabri/ui/navigation/MainBottomNavigationItem.kt
- app/src/main/java/com/vocabri/ui/main/viewmodel/MainViewModel.kt
The navigation system in Vocabri is built using Jetpack Compose Navigation. It provides a structured, type-safe way to manage screen transitions and data passing within the application. The architecture is centered around a NavHost composable, a NavHostController, and a sealed interface NavigationRoute that defines all possible destinations.
The system distinguishes between primary "Start" screens, accessible via a bottom navigation bar, and "Secondary" screens, which are navigated to from other parts of the app. This clear separation simplifies the navigation graph and user flow. The MainScreen composable acts as the root, orchestrating the display of the current screen, top app bar, and the main bottom navigation bar.
Sources: app/src/main/java/com/vocabri/ui/navigation/AppNavigation.kt, app/src/main/java/com/vocabri/ui/navigation/NavigationRoute.kt, app/src/main/java/com/vocabri/ui/main/MainScreen.kt
Core Components
The navigation architecture is composed of several key classes and composables that work together to manage the app's UI flow.
The diagram below shows the relationship between the main components involved in navigation.
AppNavigation Composable
This is the heart of the navigation system. It hosts the NavHost composable, which defines the navigation graph for the entire application. It maps string-based routes from NavigationRoute to their corresponding screen composables.
- Start Destination: The app's entry point is set to
NavigationRoute.Start.Dictionary.route. - Screen Definitions: Each screen is defined within a
composableblock. - Argument Passing: It handles passing arguments to destinations, as seen with the
DictionaryDetailsscreen, which accepts apartOfSpeechstring argument.
Sources: app/src/main/java/com/vocabri/ui/navigation/AppNavigation.kt:42-101
NavigationRoute Sealed Interface
This interface provides a type-safe way to define all navigation destinations. It is divided into two main categories: Start and Secondary.
The class diagram below illustrates the structure of the NavigationRoute sealed interface.
Start Routes
These represent the primary screens accessible from the MainBottomNavigation. Each Start route contains resources for its title and icons.
| Route | Route String | Title Resource ID |
|---|---|---|
Dictionary | dictionary | R.string.navigation_screen_title_dictionary |
Training | training | R.string.navigation_screen_title_exercise |
DiscoverMore | discover_more | R.string.navigation_screen_title_discover_more |
Settings | settings | R.string.navigation_screen_title_settings |
Sources: app/src/main/java/com/vocabri/ui/navigation/NavigationRoute.kt:40-67
Secondary Routes
These are destinations navigated to from other screens.
| Route | Route String | Description |
|---|---|---|
DictionaryDetails | group_details/{partOfSpeech} | Details screen for a specific word group. Requires a partOfSpeech argument. |
AddWord | add_word | Screen for adding a new word. |
Sources: app/src/main/java/com/vocabri/ui/navigation/NavigationRoute.kt:71-85
MainBottomNavigation Composable
This component builds the bottom navigation bar. It dynamically creates NavigationBarItem instances for each Start route. A special NavigationRoute.Empty is used as a placeholder in the center, where a floating action button (PlusItem) is overlaid to navigate to the AddWord screen.
The list of routes for the bottom bar is provided by MainViewModel.
Sources: app/src/main/java/com/vocabri/ui/navigation/MainBottomNavigation.kt:43-63, app/src/main/java/com/vocabri/ui/main/viewmodel/MainViewModel.kt:56-62
Navigation Flow
The MainScreen composable orchestrates the UI by observing the current route and conditionally displaying the appropriate TopAppBar and the MainBottomNavigation.
Navigating to a Screen
The following sequence diagram illustrates what happens when a user taps a bottom navigation icon.
Navigating with Arguments
To navigate to a screen that requires arguments, such as DictionaryDetails, the calling screen must construct the route with the required parameter.
The AppNavigation composable is responsible for extracting this argument from the NavBackStackEntry.
// Example of navigating to DictionaryDetails
navController.navigate(
NavigationRoute.Secondary.DictionaryDetails.fromGroup(partOfSpeech.name)
)
// In AppNavigation.kt
composable(
NavigationRoute.Secondary.DictionaryDetails.route,
arguments = listOf(navArgument("partOfSpeech") { type = NavType.StringType }),
) { backStackEntry ->
val partOfSpeech = backStackEntry.arguments?.getString("partOfSpeech").orEmpty()
// ... use partOfSpeech to get the correct ViewModel
}
Sources: app/src/main/java/com/vocabri/ui/navigation/NavigationRoute.kt:75-77, app/src/main/java/com/vocabri/ui/navigation/AppNavigation.kt:80-84
Conditional UI in MainScreen
The MainScreen uses the current route to decide which TopAppBar to show and whether the MainBottomNavigation should be visible. The bottom bar is only shown for Start routes.
// From MainScreen.kt
Scaffold(
// ...
topBar = {
when (currentRoute) {
NavigationRoute.Start.Dictionary.route -> DictionaryScreenTopAppBar()
// ... other routes
}
},
bottomBar = {
AnimatedVisibility(
visible = currentRoute in state.routes.map { it.route },
// ...
) {
MainBottomNavigation(...)
}
},
) { ... }
Sources: app/src/main/java/com/vocabri/ui/main/MainScreen.kt:63-99