One question, if you want animations between screen you can create custom style for each screen that overrides the default AnimatedNavHostEngine
you can define for all screens in that graph. But in styles I can't seem to find a way to pass a variable to it. For example in the documentation under ProfileTransitions.kt
you have hardcoded initialOffsetX = 1000
, but what if I wanted a different number (for example the exact width of the screen. I can define this for default animations, but not for each individual screen.
ProvideWindowInsets {
AppTheme {
val navController = rememberAnimatedNavController()
val viewModel: CustomViewModel = hiltViewModel()
// We can get width of the screen this way
BoxWithConstraints {
val width = constraints.maxWidth
val navHostEngine = rememberAnimatedNavHostEngine(
rootDefaultAnimations = RootNavGraphDefaultAnimations(
enterTransition = {
slideInHorizontally(
initialOffsetX = { width },
animationSpec = tween(
durationMillis = 700,
easing = FastOutSlowInEasing
)
)
},
exitTransition = {
slideOutHorizontally(
targetOffsetX = { -width },
animationSpec = tween(
durationMillis = 700,
easing = FastOutSlowInEasing
)
)
},
popEnterTransition = {
slideInHorizontally(
initialOffsetX = { -width },
animationSpec = tween(
durationMillis = 700,
easing = FastOutSlowInEasing
)
)
},
popExitTransition = {
slideOutHorizontally(
targetOffsetX = { width },
animationSpec = tween(
durationMillis = 700,
easing = FastOutSlowInEasing
)
)
}
),
)
DestinationsNavHost(
navGraph = NavGraphs.root,
startRoute = NavGraphs.root.startRoute,
engine = navHostEngine,
navController = navController,
modifier = Modifier
) {
animatedComposable(AScreenDestination) {
AScreen(
modifier = Modifier.statusBarsPadding(),
viewModel = viewModel,
)
}
animatedComposable(BScreenDestination) {
BScreen(
modifier = Modifier.statusBarsPadding(),
viewModel = viewModel,
)
}
}
}
}
}
In this case both will have default, then If I wanted to change the transition of BScreen
, you would need to add:
object BScreenTransition: DestinationStyle.Animated {
override fun AnimatedContentScope<NavBackStackEntry>.enterTransition(): EnterTransition? {
return when (initialState.navDestination) {
BScreenTransitionDestination ->
slideInHorizontally(
initialOffsetX = { 1000 },
animationSpec = tween(2500)
)
else -> null
}
}
override fun AnimatedContentScope<NavBackStackEntry>.exitTransition(): ExitTransition? {
return when (targetState.navDestination) {
BScreenTransitionDestination ->
slideOutHorizontally(
targetOffsetX = { -1000 },
animationSpec = tween(2500)
)
else -> null
}
}
override fun AnimatedContentScope<NavBackStackEntry>.popEnterTransition(): EnterTransition? {
return when (initialState.navDestination) {
BScreenTransitionDestination ->
slideInHorizontally(
initialOffsetX = { -1000 },
animationSpec = tween(2500)
)
else -> null
}
}
override fun AnimatedContentScope<NavBackStackEntry>.popExitTransition(): ExitTransition? {
return when (targetState.navDestination) {
BScreenTransitionDestination ->
slideOutHorizontally(
targetOffsetX = { 1000 },
animationSpec = tween(2500)
)
else -> null
}
}
}
@Destination(
style = BScreenTransition::class,
)
So the animation style would be applied.
This way you can't pass the width
to the BScreenTransition
you can only change a fixed number inside this object.
Maybe it can be done and I just don't know how.