这篇文章介绍一些Compose官方现已封装好的,能够开箱即用的动画API。
animateContentSize内容巨细动画
animateContentSize内容巨细动画用于修正组件的内容巨细时增加动画作用,常用场景为展示内容过多需求收起,点击后再将其显现完整。
fun Modifier.animateContentSize(
animationSpec: FiniteAnimationSpec<IntSize> = spring(),
finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null
): Modifier = composed(
inspectorInfo = debugInspectorInfo {
name = "animateContentSize"
properties["animationSpec"] = animationSpec
properties["finishedListener"] = finishedListener
}
) {
val scope = rememberCoroutineScope()
val animModifier = remember(scope) {
SizeAnimationModifier(animationSpec, scope)
}
animModifier.listener = finishedListener
this.clipToBounds().then(animModifier)
}
animateContentSize为Modifier的扩展办法,因此只需求组件的modifier调用该办法,便可在该组件的内容进行变化重组的时候呈现该动画。
animateContentSize内含两个参数,都有默认值,第一个参数为animationSpec动画标准,默以为SpringSpec弹性动画,可自定义动画作用,第二个参数为动画完成时的监听,默以为空。 简略示例:
var change by remember { mutableStateOf(false) }
Column(modifier = Modifier.animateContentSize()) {
Text(text = "点击改动内容巨细", modifier = Modifier.clickable { change = !change })
if (change) {
Text(
text = "这是一个大方块",
modifier = Modifier
.size(100.dp)
.background(Color.Gray),
)
}
}
AnimatedVisibility可见性动画
AnimatedVisibility可见性动画用于组件的呈现和消失时增加动画作用。
@Composable
fun AnimatedVisibility(
visible: Boolean,
modifier: Modifier = Modifier,
enter: EnterTransition = fadeIn() + expandIn(),
exit: ExitTransition = shrinkOut() + fadeOut(),
label: String = "AnimatedVisibility",
content: @Composable() AnimatedVisibilityScope.() -> Unit
) {
val transition = updateTransition(visible, label)
AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)
}
AnimatedVisibility有6个参数,只要第一个和最终一个参数有必要填入,其他参数都有默认值。
- visible:定义内容是否应该可见,true 为可见,false 为不行见。
- modifier:修饰符,Compose里随处可见。
- enter:内容可见时的动画,默以为fadeIn() + expandIn(),大致意思为淡入并扩展开。
- exit:内容不行见时的动画,默以为shrinkOut() + fadeOut(),大致意思为缩小并淡出消失。
- label:标签,用于区分不同动画。
- content:增加可见性动画作用的组合项内容。
简略示例:
var change by remember { mutableStateOf(false) }
Column {
Text(text = "点击改动可见性", modifier = Modifier.clickable { change = !change })
AnimatedVisibility(visible = change) {
Text(
text = "这是一个大方块",
modifier = Modifier
.size(100.dp)
.background(Color.Gray),
)
}
}
当然可完全能够自定义可见/不行见时的动画作用:
var change by remember { mutableStateOf(false) }
Column {
Text(text = "点击改动可见性", modifier = Modifier.clickable { change = !change })
AnimatedVisibility(
visible = change,
enter = slideInVertically(
initialOffsetY = { fullHeight -> -fullHeight },
animationSpec = tween(durationMillis = 150, easing = LinearOutSlowInEasing)
),
exit = slideOutVertically(
targetOffsetY = { fullHeight -> -fullHeight },
animationSpec = tween(durationMillis = 250, easing = FastOutSlowInEasing)
)
) {
Text(
text = "这是一个大方块",
modifier = Modifier
.size(100.dp)
.background(Color.Gray),
)
}
}
animateValueAsState单一值特点动画
特点动画就是通过不断地修正特点值来完成的。animateValueAsState对恣意值的特点动画。官方提供了一整套的api来完成简略的单一值特点动画。 实际运用的时候按需选择即可。
@Composable
fun animateDpAsState(
targetValue: Dp,
animationSpec: AnimationSpec<Dp> = dpDefaultSpring,
label: String = "DpAnimation",
finishedListener: ((Dp) -> Unit)? = null
): State<Dp> {
return animateValueAsState(
targetValue,
Dp.VectorConverter,
animationSpec,
label = label,
finishedListener = finishedListener
)
}
以animateDpAsState为例,共4个参数,第一个为目标值,有必要填入,其他参数都有默认值,第二个参数为animationSpec动画标准,默以为SpringSpec弹性动画,可自定义动画作用,第三第四个参数前面呈现过,按字面意思也可理解就不细说了。整个动画会以当前值为开端值,传入的targetValue为完毕值,以animationSpec动画标准进行动画作用。
简略示例:
var small by remember { mutableStateOf(true) }
val size: Dp by animateDpAsState(
targetValue = if (small) 40.dp else 100.dp
)
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(onClick = { small = !small }) {
Text(text = "改动方块巨细")
}
Box(
modifier = Modifier
.size(size)
.background(Color.LightGray)
)
}
updateTransition多值动画
updateTransition能够保存一个或多个子动画,当状态发生改动时,多个动画同时进行。能够运用animate*扩展办法增加子动画。
简略示例:运用animateDp和 animateColor同时进行两个子动画
var change by remember { mutableStateOf(false) }
val transition = updateTransition(targetState = change, label = "多值动画")
val offset by transition.animateDp(label = "") { change ->
if (change) 50.dp else 0.dp
}
val background by transition.animateColor(label = "") { change ->
if (change) Color.Gray else Color.Blue
}
Column(modifier = Modifier.fillMaxWidth()) {
Text(text = "点击进行多个动画", modifier = Modifier.clickable { change = !change })
Text(
text = "这是一个大方块",
modifier = Modifier
.size(100.dp)
.offset(x = offset)
.background(background),
)
}
rememberInfiniteTransition无限重复动画
rememberInfiniteTransition能够进行无限重复动画,也相同能够保存一个或多个子动画,可是,这些动画一进入组合阶段就开端运转,除非被移除,否则不会中止,能够运用 animateColor、animatedFloat 或 animatedValue 增加子动画。
简略示例:运用animatedValue增加子动画改动巨细size,而且运用animatedFloat增加子动画改动巨细透明度alpha
val infiniteTransition = rememberInfiniteTransition()
val size by infiniteTransition.animateValue(
initialValue = 100.dp,
targetValue = 200.dp,
typeConverter = TwoWayConverter({ AnimationVector1D(it.value) }, { it.value.dp }),
animationSpec = infiniteRepeatable(
animation = tween(1000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
)
)
val alpha by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(1000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
)
)
Box(
Modifier
.size(size)
.padding(20.dp)
.alpha(alpha)
.background(Color.Red)
)
最终
最终,运用上面这些动画API能够达到一些简略的动画作用,但如果想要一些杂乱的自定义的动画作用,能够运用animationSpec这个参数,详细见Compose动画学习之AnimationSpec。