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
我通过图像的 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