As you mentioned, this animation should be implemented by the Navigation Library and there's a ticket opened to that.
Having that in mind, I'm leaving my answer here and I hope it helps...
I'll break it in three parts:
- The container:
@Composable
fun SlideInAnimationScreen() {
// I'm using the same duration for all animations.
val animationTime = 300
// This state is controlling if the second screen is being displayed or not
var showScreen2 by remember { mutableStateOf(false) }
// This is just to give that dark effect when the first screen is closed...
val color = animateColorAsState(
targetValue = if (showScreen2) Color.DarkGray else Color.Red,
animationSpec = tween(
durationMillis = animationTime,
easing = LinearEasing
)
)
Box(Modifier.fillMaxSize()) {
// Both Screen1 and Screen2 are declared here...
}
}
- The first screen just do a small slide to create that parallax effect. I'm also changing the background color from Red to Dark just to give this overlap/hide/dark effect.
// Screen 1
AnimatedVisibility(
!showScreen2,
modifier = Modifier.fillMaxSize(),
enter = slideInHorizontally(
initialOffsetX = { -300 }, // small slide 300px
animationSpec = tween(
durationMillis = animationTime,
easing = LinearEasing // interpolator
)
),
exit = slideOutHorizontally(
targetOffsetX = { -300 }, =
animationSpec = tween(
durationMillis = animationTime,
easing = LinearEasing
)
)
) {
Box(
Modifier
.fillMaxSize()
.background(color.value) // animating the color
) {
Button(modifier = Modifier.align(Alignment.Center),
onClick = {
showScreen2 = true
}) {
Text(text = "Ok")
}
}
}
- The second is really sliding from the edges.
// Screen 2
AnimatedVisibility(
showScreen2,
modifier = Modifier.fillMaxSize(),
enter = slideInHorizontally(
initialOffsetX = { it }, // it == fullWidth
animationSpec = tween(
durationMillis = animationTime,
easing = LinearEasing
)
),
exit = slideOutHorizontally(
targetOffsetX = { it },
animationSpec = tween(
durationMillis = animationTime,
easing = LinearEasing
)
)
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Blue)
) {
Button(modifier = Modifier.align(Alignment.Center),
onClick = {
showScreen2 = false
}) {
Text(text = "Back")
}
}
}
Here is the result:
