refactor navigation code

This commit is contained in:
Owen LeJeune
2022-02-10 16:29:36 -05:00
parent fe08d2dd02
commit 78f0a874c9
5 changed files with 130 additions and 83 deletions

View File

@@ -18,16 +18,11 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.owenlejeune.tvtime.ui.components.NavItems import com.owenlejeune.tvtime.ui.navigation.BottomNavItem
import com.owenlejeune.tvtime.ui.screens.FavouritesTab import com.owenlejeune.tvtime.ui.navigation.BottomNavigationRoutes
import com.owenlejeune.tvtime.ui.screens.MoviesTab import com.owenlejeune.tvtime.ui.navigation.MainNavigationRoutes
import com.owenlejeune.tvtime.ui.screens.SettingsTab
import com.owenlejeune.tvtime.ui.screens.TvTab
import com.owenlejeune.tvtime.ui.theme.TVTimeTheme import com.owenlejeune.tvtime.ui.theme.TVTimeTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@@ -39,20 +34,31 @@ class MainActivity : ComponentActivity() {
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MyApp() { fun MyApp() {
TVTimeTheme { TVTimeTheme {
val appNavController = rememberNavController()
Box {
MainNavigationRoutes(navController = appNavController)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainAppView(appNavController: NavController) {
val navController = rememberNavController() val navController = rememberNavController()
val appBarTitle = remember { mutableStateOf(NavItems.Items[0].name) } val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
val appBarTitle = remember { mutableStateOf(BottomNavItem.Items[0].name) }
val decayAnimationSpec = rememberSplineBasedDecay<Float>() val decayAnimationSpec = rememberSplineBasedDecay<Float>()
val scrollBehavior = remember(decayAnimationSpec) { val scrollBehavior = remember(decayAnimationSpec) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec) TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec)
} }
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
Scaffold( Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
backgroundColor = MaterialTheme.colorScheme.background, backgroundColor = MaterialTheme.colorScheme.background,
@@ -69,19 +75,17 @@ fun MyApp() {
) )
}, },
floatingActionButton = { floatingActionButton = {
if (currentRoute in listOf(NavItems.Movies.route, NavItems.TV.route)) { if (currentRoute in listOf(BottomNavItem.Movies.route, BottomNavItem.TV.route)) {
SearchFab() SearchFab()
} }
} }
) { innerPadding -> ) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) { Box(modifier = Modifier.padding(innerPadding)) {
NavigationRoutes(navController = navController) BottomNavigationRoutes(navController = navController)
}
} }
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun TopBar(title: MutableState<String>, scrollBehavior: TopAppBarScrollBehavior) { private fun TopBar(title: MutableState<String>, scrollBehavior: TopAppBarScrollBehavior) {
LargeTopAppBar( LargeTopAppBar(
@@ -96,12 +100,28 @@ private fun BottomNavBar(navController: NavController, appBarTitle: MutableState
val currentRoute = navBackStackEntry?.destination?.route val currentRoute = navBackStackEntry?.destination?.route
NavigationBar { NavigationBar {
NavItems.Items.forEachIndexed { index, item -> BottomNavItem.Items.forEach { item ->
NavigationBarItem( NavigationBarItem(
icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) }, icon = { Icon(painter = painterResource(id = item.icon), contentDescription = null) },
label = { Text(item.name) }, label = { Text(item.name) },
selected = currentRoute == item.route, selected = currentRoute == item.route,
onClick = { onClick = {
onBottomAppBarItemClicked(
navController = navController,
appBarTitle = appBarTitle,
item = item
)
}
)
}
}
}
private fun onBottomAppBarItemClicked(
navController: NavController,
appBarTitle: MutableState<String>,
item: BottomNavItem
) {
appBarTitle.value = item.name appBarTitle.value = item.name
navController.navigate(item.route) { navController.navigate(item.route) {
navController.graph.startDestinationRoute?.let { screenRoute -> navController.graph.startDestinationRoute?.let { screenRoute ->
@@ -113,28 +133,6 @@ private fun BottomNavBar(navController: NavController, appBarTitle: MutableState
restoreState = true restoreState = true
} }
} }
)
}
}
}
@Composable
private fun NavigationRoutes(navController: NavHostController) {
NavHost(navController = navController, startDestination = NavItems.Movies.route) {
composable(NavItems.Movies.route) {
MoviesTab()
}
composable(NavItems.TV.route) {
TvTab()
}
composable(NavItems.Favourites.route) {
FavouritesTab()
}
composable(NavItems.Settings.route) {
SettingsTab()
}
}
}
@Composable @Composable
private fun SearchFab() { private fun SearchFab() {

View File

@@ -1,16 +0,0 @@
package com.owenlejeune.tvtime.ui.components
import com.owenlejeune.tvtime.R
sealed class NavItems(val name: String, val icon: Int, val route: String) {
companion object {
val Items = listOf(Movies, TV, Favourites, Settings)
}
object Movies: NavItems("Movies", R.drawable.ic_movie, "movies_route")
object TV: NavItems("TV", R.drawable.ic_tv, "tv_route")
object Favourites: NavItems("Favourites", R.drawable.ic_favorite, "favourites_route")
object Settings: NavItems("Settings", R.drawable.ic_settings, "settings_route")
}

View File

@@ -0,0 +1,16 @@
package com.owenlejeune.tvtime.ui.navigation
import com.owenlejeune.tvtime.R
sealed class BottomNavItem(val name: String, val icon: Int, val route: String) {
companion object {
val Items = listOf(Movies, TV, Favourites, Settings)
}
object Movies: BottomNavItem("Movies", R.drawable.ic_movie, "movies_route")
object TV: BottomNavItem("TV", R.drawable.ic_tv, "tv_route")
object Favourites: BottomNavItem("Favourites", R.drawable.ic_favorite, "favourites_route")
object Settings: BottomNavItem("Settings", R.drawable.ic_settings, "settings_route")
}

View File

@@ -0,0 +1,8 @@
package com.owenlejeune.tvtime.ui.navigation
sealed class MainNavItem(val route: String) {
object MainView: MainNavItem("main_route")
object DetailView: MainNavItem("detail_route")
}

View File

@@ -0,0 +1,41 @@
package com.owenlejeune.tvtime.ui.navigation
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.owenlejeune.tvtime.MainAppView
import com.owenlejeune.tvtime.ui.screens.FavouritesTab
import com.owenlejeune.tvtime.ui.screens.MoviesTab
import com.owenlejeune.tvtime.ui.screens.SettingsTab
import com.owenlejeune.tvtime.ui.screens.TvTab
@Composable
fun MainNavigationRoutes(navController: NavHostController) {
NavHost(navController = navController, startDestination = MainNavItem.MainView.route) {
composable(MainNavItem.MainView.route) {
MainAppView(appNavController = navController)
}
composable(MainNavItem.DetailView.route) {
}
}
}
@Composable
fun BottomNavigationRoutes(navController: NavHostController) {
NavHost(navController = navController, startDestination = BottomNavItem.Movies.route) {
composable(BottomNavItem.Movies.route) {
MoviesTab()
}
composable(BottomNavItem.TV.route) {
TvTab()
}
composable(BottomNavItem.Favourites.route) {
FavouritesTab()
}
composable(BottomNavItem.Settings.route) {
SettingsTab()
}
}
}