feat: add navigation transitions for improved user experience between screens
This commit is contained in:
@@ -17,6 +17,11 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.slideInHorizontally
|
||||||
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
import androidx.navigation.NavType
|
import androidx.navigation.NavType
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
@@ -102,18 +107,48 @@ fun MainApp() {
|
|||||||
.padding(innerPadding),
|
.padding(innerPadding),
|
||||||
color = MaterialTheme.colorScheme.background,
|
color = MaterialTheme.colorScheme.background,
|
||||||
) {
|
) {
|
||||||
|
val tabRoutes = setOf(Routes.TABLES, Routes.SETTINGS)
|
||||||
NavHost(
|
NavHost(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = Routes.TABLES,
|
startDestination = Routes.TABLES,
|
||||||
) {
|
) {
|
||||||
composable(Routes.TABLES) {
|
// Fade between bottom navigation tabs
|
||||||
|
composable(
|
||||||
|
route = Routes.TABLES,
|
||||||
|
enterTransition = {
|
||||||
|
if (initialState.destination.route in tabRoutes && targetState.destination.route in tabRoutes) {
|
||||||
|
fadeIn(tween(200))
|
||||||
|
} else {
|
||||||
|
fadeIn(tween(150))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
exitTransition = {
|
||||||
|
if (initialState.destination.route in tabRoutes && targetState.destination.route in tabRoutes) {
|
||||||
|
fadeOut(tween(200))
|
||||||
|
} else {
|
||||||
|
fadeOut(tween(150))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
popEnterTransition = { fadeIn(tween(180)) },
|
||||||
|
popExitTransition = { fadeOut(tween(180)) },
|
||||||
|
) {
|
||||||
ListsScreen(
|
ListsScreen(
|
||||||
onNavigateToList = { listId -> navController.navigate("list/$listId") },
|
onNavigateToList = { listId -> navController.navigate("list/$listId") },
|
||||||
onNavigateToSettings = { navController.navigate(Routes.SETTINGS) },
|
onNavigateToSettings = { navController.navigate(Routes.SETTINGS) },
|
||||||
onNavigateToLogs = { navController.navigate(Routes.LOGS) },
|
onNavigateToLogs = { navController.navigate(Routes.LOGS) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(Routes.SETTINGS) {
|
composable(
|
||||||
|
route = Routes.SETTINGS,
|
||||||
|
enterTransition = {
|
||||||
|
if (initialState.destination.route in tabRoutes && targetState.destination.route in tabRoutes) fadeIn(tween(200)) else fadeIn(tween(150))
|
||||||
|
},
|
||||||
|
exitTransition = {
|
||||||
|
if (initialState.destination.route in tabRoutes && targetState.destination.route in tabRoutes) fadeOut(tween(200)) else fadeOut(tween(150))
|
||||||
|
},
|
||||||
|
popEnterTransition = { fadeIn(tween(180)) },
|
||||||
|
popExitTransition = { fadeOut(tween(180)) },
|
||||||
|
) {
|
||||||
SettingsScreen(
|
SettingsScreen(
|
||||||
onNavigateBack = { navController.popBackStack() },
|
onNavigateBack = { navController.popBackStack() },
|
||||||
onNavigateToLogs = { navController.navigate(Routes.LOGS) },
|
onNavigateToLogs = { navController.navigate(Routes.LOGS) },
|
||||||
@@ -123,12 +158,23 @@ fun MainApp() {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(Routes.LOGS) {
|
// Horizontal slide for Logs screen
|
||||||
|
composable(
|
||||||
|
route = Routes.LOGS,
|
||||||
|
enterTransition = { slideInHorizontally(animationSpec = tween(220), initialOffsetX = { it }) + fadeIn(tween(220)) },
|
||||||
|
exitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { -it / 3 }) + fadeOut(tween(180)) },
|
||||||
|
popEnterTransition = { slideInHorizontally(animationSpec = tween(220), initialOffsetX = { -it }) + fadeIn(tween(220)) },
|
||||||
|
popExitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { it / 3 }) + fadeOut(tween(180)) },
|
||||||
|
) {
|
||||||
LogsScreen(onNavigateBack = { navController.popBackStack() })
|
LogsScreen(onNavigateBack = { navController.popBackStack() })
|
||||||
}
|
}
|
||||||
composable(
|
composable(
|
||||||
route = Routes.LIST_DETAIL,
|
route = Routes.LIST_DETAIL,
|
||||||
arguments = listOf(navArgument("listId") { type = NavType.StringType }),
|
arguments = listOf(navArgument("listId") { type = NavType.StringType }),
|
||||||
|
enterTransition = { slideInHorizontally(animationSpec = tween(240), initialOffsetX = { it }) + fadeIn(tween(240)) },
|
||||||
|
exitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { -it / 2 }) + fadeOut(tween(180)) },
|
||||||
|
popEnterTransition = { slideInHorizontally(animationSpec = tween(240), initialOffsetX = { -it }) + fadeIn(tween(240)) },
|
||||||
|
popExitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { it / 2 }) + fadeOut(tween(180)) },
|
||||||
) { backStackEntry ->
|
) { backStackEntry ->
|
||||||
val listId = backStackEntry.arguments?.getString("listId") ?: return@composable
|
val listId = backStackEntry.arguments?.getString("listId") ?: return@composable
|
||||||
ListDetailScreen(listId = listId, onNavigateBack = { navController.popBackStack() })
|
ListDetailScreen(listId = listId, onNavigateBack = { navController.popBackStack() })
|
||||||
|
|||||||
Reference in New Issue
Block a user