Android 动画和过渡
(一) 动画
JetpackCompose提供了强大且可扩展的API,可以轻松地在应用程序的UI中实现各种动画。下面描述了如何使用这些API以及根据动画场景使用哪些API。
动画在现代移动应用程序中至关重要,以实现流畅和可理解的用户体验。许多Jetpack Compose Animation API都可以作为可组合的函数提供,就像布局和其他UI元素一样,并且它们由使用Kotlin协程暂停函数构建的低级API支持。本指南从在许多实际场景中有用的高级API开始,并继续解释为您提供进一步控制和定制的低级API。
下图可帮助决定用什么API来实现动画。
(1)如果要设置布局中内容更改的动画:
如果要设置外观和消失的动画:
使用“动画可见性”。
基于状态交换内容:
如果您正在交叉阅读内容:
使用交叉淡入淡出。
否则,请使用AnimatedContent。
否则,请使用Modifier.animateContentSize。
(2)如果动画基于状态:
如果动画发生在合成期间:
如果动画是无限的:
使用rememberInfiniteTransition。
如果同时设置多个值的动画:
使用updateTransition。
否则,请使用animate*AsState。
(3)如果要对动画时间进行精细控制:
使用动画,例如TargetBasedAnimation或DecayAnimation。
(4)如果动画是真实的唯一来源
使用可设置动画。
(5)否则,请使用AnimationState或animate。
1.高级动画API
Compose为许多应用程序中使用的几种常见动画模式提供了高级动画API。这些API是为符合Material Design Motion的最佳实践而定制的。
1.1动画可见性
AnimatedVisibility可组合设置其内容的外观和消失的动画。
代码示例:
var editable by remember { mutableStateOf(true) }
AnimatedVisibility(visible = editable) {
Text(text = “Edit”)
}
默认情况下,内容通过淡入和展开来显示,而通过淡出和收缩来消失。可以通过指定EnterTransition和ExitTransition来自定义转换。
代码示例:
var visible by remember { mutableStateOf(true) }
val density = LocalDensity.current
AnimatedVisibility(
visible = visible,
enter = slideInVertically {
// Slide in from 40 dp from the top.
with(density) { -40.dp.roundToPx() }
} + expandVertically(
// Expand from the top.
expandFrom = Alignment.Top
) + fadeIn(
// Fade in with the initial alpha of 0.3f.
initialAlpha = 0.3f
),
exit = slideOutVertically() + shrinkVertically() + fadeOut()
) {
Text(“Hello”, Modifier.fillMaxWidth().height(200.dp))
}
1.2为子对象设置进出动画
AnimateVisibility中的内容(直接或间接子对象)可以使用animateEnterExit修改器为每个子对象指定不同的动画行为。每个孩子的视觉效果是在AnimatedVisibility组合中指定的动画和孩子自己的进入和退出动画的组合。
AnimatedVisibility(
visible = visible,
enter = fadeIn(),
exit = fadeOut()
) {
// Fade in/out the background and the foreground.
Box(Modifier.fillMaxSize().background(Color.DarkGray)) {
Box(
Modifier
.align(Alignment.Center)
.animateEnterExit(
// Slide in/out the inner box.
enter = slideInVertically(),
exit = slideOutVertically()
)
.sizeIn(minWidth = 256.dp, minHeight = 64.dp)
.background(Color.Red)
) {
// Content of the notification…
}
}
}
1.3添加自定义动画
如果要在内置的进入和退出动画之外添加自定义动画效果,要通过AnimatedVisibility的content lambda中的Transition属性访问基础的Transition实例。添加到“过渡”实例的任何动画状态都将与AnimatedVisibility的进入和退出动画同时运行。AnimatedVisibility将一直等到“过渡”中的所有动画都完成后再删除其内容。对于独立于Transition创建的退出动画(例如使用animateAsState),AnimatedVisibility将无法解释它们,因此可能会在完成之前删除可组合的内容
AnimatedVisibility(
visible = visible,
enter = fadeIn(),
exit = fadeOut()
) { // this: AnimatedVisibilityScope
// Use AnimatedVisibilityScope#transition to add a custom animation
// to the AnimatedVisibility.
val background by transition.animateColor { state ->
i