feat: enhance navigation transitions for Logs and ListDetail screens with container-aware animations

This commit is contained in:
2025-11-11 21:43:36 +01:00
parent de4a04fc3c
commit edd925e1bb
2 changed files with 52 additions and 12 deletions
@@ -18,7 +18,8 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:theme="@style/Theme.CollabTable"> android:theme="@style/Theme.CollabTable"
android:enableOnBackInvokedCallback="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@@ -17,11 +17,10 @@ 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.AnimatedContentTransitionScope
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut 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
@@ -158,23 +157,63 @@ fun MainApp() {
}, },
) )
} }
// Horizontal slide for Logs screen // Horizontal slide for Logs screen (container-aware for predictive back)
composable( composable(
route = Routes.LOGS, route = Routes.LOGS,
enterTransition = { slideInHorizontally(animationSpec = tween(220), initialOffsetX = { it }) + fadeIn(tween(220)) }, enterTransition = {
exitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { -it / 3 }) + fadeOut(tween(180)) }, slideIntoContainer(
popEnterTransition = { slideInHorizontally(animationSpec = tween(220), initialOffsetX = { -it }) + fadeIn(tween(220)) }, AnimatedContentTransitionScope.SlideDirection.Left,
popExitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { it / 3 }) + fadeOut(tween(180)) }, animationSpec = tween(240),
) + fadeIn(tween(200))
},
exitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = tween(200),
) + fadeOut(tween(180))
},
popEnterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(240),
) + fadeIn(tween(200))
},
popExitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(200),
) + 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)) }, enterTransition = {
exitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { -it / 2 }) + fadeOut(tween(180)) }, slideIntoContainer(
popEnterTransition = { slideInHorizontally(animationSpec = tween(240), initialOffsetX = { -it }) + fadeIn(tween(240)) }, AnimatedContentTransitionScope.SlideDirection.Left,
popExitTransition = { slideOutHorizontally(animationSpec = tween(200), targetOffsetX = { it / 2 }) + fadeOut(tween(180)) }, animationSpec = tween(260),
) + fadeIn(tween(220))
},
exitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = tween(200),
) + fadeOut(tween(180))
},
popEnterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(260),
) + fadeIn(tween(220))
},
popExitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(200),
) + 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() })