正如您所提到的,这个动画应该由导航库实现,并且有一张开给那个的票 https://issuetracker.google.com/issues/172112072.
考虑到这一点,我将我的答案留在这里,希望它有所帮助......
我将把它分成三个部分:
- 容器:
@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...
}
}
- 第一个屏幕只需做一个小幻灯片即可创建视差效果。我还将背景颜色从红色更改为深色,只是为了提供重叠/隐藏/深色效果。
// 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")
}
}
}
- 第二个确实是从边缘滑落。
// 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")
}
}
}
结果如下: