SceneOverrideEntryTransitionsSample
@Sampled
@Composable
fun SceneOverrideEntryTransitionsSample() {
val backStack = rememberNavBackStack(A)
NavDisplay(
backStack,
onBack = { backStack.removeLastOrNull() },
entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()),
// the Scene overrides the NavEntry's slide vertical with slide horizontal transitions
sceneStrategies = listOf(SceneOverrideEntryTransitionsSceneStrategy()),
entryProvider =
entryProvider {
entry<A> { BlueBox("A") { backStack.add(B) } }
// the entry defines slide vertical transitions
entry<B>(
metadata =
metadata {
put(NavDisplay.TransitionKey) { slideVertical }
put(NavDisplay.PopTransitionKey) { slideVertical }
put(NavDisplay.PredictivePopTransitionKey, { _: Int -> slideVertical })
}
) {
RedBox("B")
}
},
)
}
private class SceneOverrideEntryTransitionsSceneStrategy<T : Any>() : SceneStrategy<T> {
override fun SceneStrategyScope<T>.calculateScene(entries: List<NavEntry<T>>): Scene<T>? {
if (entries.isEmpty()) return null
return SceneOverrideEntryTransitionsScene(entries.last(), entries.dropLast(1))
}
}
private class SceneOverrideEntryTransitionsScene<T : Any>(
val currentEntry: NavEntry<T>,
override val previousEntries: List<NavEntry<T>>,
) : Scene<T> {
override val key = currentEntry.contentKey
override val entries: List<NavEntry<T>> = listOf(currentEntry)
override val content: @Composable (() -> Unit) = { currentEntry.Content() }
// super.metadata defaults to [entries.last()]'s metadata
// so this overrides the last entry's transitions
override val metadata: Map<String, Any> = super.metadata + sceneTransitions
}
private val sceneTransitions = metadata {
put(NavDisplay.TransitionKey) { slideHorizontal }
put(NavDisplay.PopTransitionKey) { slideHorizontal }
put(NavDisplay.PredictivePopTransitionKey) { slideHorizontal }
}
private val duration = 5000
private val animSpec: FiniteAnimationSpec<IntOffset> =
tween(duration, easing = LinearOutSlowInEasing)
private val slideHorizontal =
slideInHorizontally(animSpec) { it / 2 } togetherWith slideOutHorizontally(animSpec) { -it / 2 }
private val slideVertical =
slideInVertically(animSpec) { it / 2 } togetherWith slideOutVertically(animSpec) { -it / 2 }