Android Jetpack Compose (Composable) 用动画改变图像源

Android Jetpack Compose (Composable) Change Image source with animation

我通过图像的 painter 属性将矢量可绘制对象设置为源。现在我想更改源代码,但也要为更改设置动画。我所说的动画不是指使用路径数据变形动画,而是我想要简单的 FadeIn、FadeOut 效果。因此,一旦更改源,我希望隐藏前一个并显示带有淡入淡出动画的当前可绘制对象。

现在我正在做一个解决方法,我使用 2 个图像和两个不同图像的来源,并使用 AnimatedVisibility 更改图像的可见性,以匹配主题。有没有标准的方法来改变动画源?

这是我使用的 hack,在我看来非常丑陋

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun AnimatedImage(modifier: Modifier, isLightTheme: Boolean, srcLight: Int = R.drawable.ic_sun, srcDark: Int = R.drawable.ic_moon) {

    val colors = LocalColors.current
    val (enter, exit) = remember {
        arrayListOf(
            fadeIn(animationSpec = tween(durationMillis = 1500)),
            fadeOut(animationSpec = tween(durationMillis = 500))
        )
    }

    AnimatedVisibility(
        visible = !isLightTheme,
        enter = enter as EnterTransition,
        exit = exit as ExitTransition
    ) {
        Image(
            painter = painterResource(id = srcDark), contentDescription = "",
            colorFilter = ColorFilter.tint(colors.secondsArrow),
            modifier = modifier
        )
    }

    AnimatedVisibility(
        visible = isLightTheme,
        enter = enter,
        exit = exit
    ) {
        Image(
            painter = painterResource(id = srcLight), contentDescription = "",
            colorFilter = ColorFilter.tint(colors.secondsArrow),
            modifier = modifier
        )
    }
}

您可以使用基本的Crossfade动画:

Crossfade(
    flag,
    animationSpec = tween(1000)
) { targetState ->
    Image(
        painterResource(if (targetState) R.drawable.ic_redo else R.drawable.ic_undo),
        contentDescription = null,
        modifier = Modifier.background(Color.Black)
    )
}

或者如果你需要一个更复杂的,你可以使用AnimatedContent——我的例子相当于你的双AnimatedVisibility:

AnimatedContent(
    flag,
    transitionSpec = {
        fadeIn(animationSpec = tween(durationMillis = 1500)) with
                fadeOut(animationSpec = tween(durationMillis = 500))
    }
) { targetState ->
    Image(
        painterResource(if (targetState) R.drawable.ic_redo else R.drawable.ic_undo),
        contentDescription = null,
        modifier = Modifier.background(Color.Black)
    )
}

请注意,在这两种情况下都需要使用 targetState 在内容 lambda 中传递,因为此 lambda 在转换过程中被多次重组。

您可以在 Compose Animation 中找到更多信息 documentation