如何在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

考虑到这一点,我将在这里留下我的答案,希望它对您有所帮助...

我会分成三个部分:

  1. 容器:
@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...
    }
}
  1. 第一个屏幕只是做一个小幻灯片来创建视差效果。我还将背景颜色从红色更改为深色,以提供这种 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")
        }
    }
}
  1. 第二个真的是从边缘滑出来的
// 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 没有导航组件的滑动。

https://issuetracker.google.com/issues/172112072

现在我们有了官方的解决方案。最近 Google Accompanist 添加了一个库,它为 Jetpack Navigation Compose 提供 Compose Animation 支持..

https://github.com/google/accompanist/tree/main/navigation-animation