如何在android中实现滑入和滑出动画 compose between two Views Synchronized
How to achieve slide in and out animation in android compose between two Views Synchronized
我知道我可以使用 AnimatedVisibility
Composable 功能并实现可见性动画的滑入动画,但我想要实现的是当一个布局在进入动画时另一个在退出动画时,类似于下图。
NB : 我知道我应该为不同的屏幕使用 Navigation compose 并且目的地之间的动画仍在开发中,但我想在一部分的内容上实现这一点屏幕,类似于 CrossFade 动画。
正如您所说,这个动画应该由导航库实现,并且有a ticket opened to that。
考虑到这一点,我将在这里留下我的答案,希望它对您有所帮助...
我会分成三个部分:
- 容器:
@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...
}
}
- 第一个屏幕只是做一个小幻灯片来创建视差效果。我还将背景颜色从红色更改为深色,以提供这种 overlap/hide/dark 效果。
// 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")
}
}
}
结果如下:
在深入研究 CrossFade 的代码后,我为交叉幻灯片实现了一个类似的代码,它在按下后退按钮时启用反向动画
这里是:https://gist.github.com/DavidIbrahim/5f4c0387b571f657f4de976822c2a225
用法示例
@Composable
fun CrossSlideExample(){
var currentPage by remember { mutableStateOf("A") }
CrossSlide(targetState = currentPage, reverseAnimation: Boolean = false) { screen ->
when (screen) {
"A" -> Text("Page A")
"B" -> Text("Page B")
}
}
}
截至目前,我们没有任何可与 Compose 中的 Activity
过渡相媲美的东西。
我希望 Jetpack 应该在他们身上工作。大量过渡 API 要么 internal
要么 private
到 Compose 库,因此实现一个好的 API 更难。
如果用于生产,请将 Activity/Fragment
与导航主机一起使用。如果不使用 AnimatedVisibility
没有导航组件的滑动。
现在我们有了官方的解决方案。最近 Google Accompanist 添加了一个库,它为 Jetpack Navigation Compose 提供 Compose Animation 支持..
https://github.com/google/accompanist/tree/main/navigation-animation
我知道我可以使用 AnimatedVisibility
Composable 功能并实现可见性动画的滑入动画,但我想要实现的是当一个布局在进入动画时另一个在退出动画时,类似于下图。
NB : 我知道我应该为不同的屏幕使用 Navigation compose 并且目的地之间的动画仍在开发中,但我想在一部分的内容上实现这一点屏幕,类似于 CrossFade 动画。
正如您所说,这个动画应该由导航库实现,并且有a ticket opened to that。
考虑到这一点,我将在这里留下我的答案,希望它对您有所帮助...
我会分成三个部分:
- 容器:
@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...
}
}
- 第一个屏幕只是做一个小幻灯片来创建视差效果。我还将背景颜色从红色更改为深色,以提供这种 overlap/hide/dark 效果。
// 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")
}
}
}
结果如下:
在深入研究 CrossFade 的代码后,我为交叉幻灯片实现了一个类似的代码,它在按下后退按钮时启用反向动画
这里是:https://gist.github.com/DavidIbrahim/5f4c0387b571f657f4de976822c2a225
用法示例
@Composable
fun CrossSlideExample(){
var currentPage by remember { mutableStateOf("A") }
CrossSlide(targetState = currentPage, reverseAnimation: Boolean = false) { screen ->
when (screen) {
"A" -> Text("Page A")
"B" -> Text("Page B")
}
}
}
截至目前,我们没有任何可与 Compose 中的 Activity
过渡相媲美的东西。
我希望 Jetpack 应该在他们身上工作。大量过渡 API 要么 internal
要么 private
到 Compose 库,因此实现一个好的 API 更难。
如果用于生产,请将 Activity/Fragment
与导航主机一起使用。如果不使用 AnimatedVisibility
没有导航组件的滑动。
现在我们有了官方的解决方案。最近 Google Accompanist 添加了一个库,它为 Jetpack Navigation Compose 提供 Compose Animation 支持..
https://github.com/google/accompanist/tree/main/navigation-animation