Animatable:
- Animatable是底层的Compose动画实现。之前文章写过的animateXXAsState,其实都是基于Animatable实现的。
AnimationVector
- 这是 AnimationVector1D、AnimationVector2D、AnimationVector3D 和 AnimationVector4D 的基类。
- 为了对任意类型进行动画处理,需要提供一个 TwoWayConverter 来定义如何将该任意类型 T 转换为 AnimationVector,反之亦然。
- 根据这个类型 T 有多少维度,它可能需要转换为 AnimationVector 的任何子类。
- 例如,基于位置的对象应转换为 AnimationVector2D,而描述矩形边界的对象应转换为 AnimationVector4D。
TwoWayConverter
- Compose提供的一个用于做某个泛型数据,根据某些规则做转换成AnimationVector的工具库
- 根据上面的解释,比如我们可以将dp,转换成对应的AnimationVector,让Compose的动画能够针对dp值,去做对应的动画处理。
Dp.VectorConvertor
private val DpToVector: TwoWayConverter<Dp, AnimationVector1D> = TwoWayConverter(
convertToVector = { AnimationVector1D(it.value) },//将dp转换成AnimationVector1D
convertFromVector = { Dp(it.value) }//将Vector数据,转换为开发者常用的dp
)
##实用Animatable
- 用dp作为动画基础,创建Animatable的实例如下:
val anim = remember {
Animatable(330.dp, Dp.VectorConverter)
}
- 动画的运行:
val anim = remember {
Animatable(330.dp, Dp.VectorConverter)
}
anim.animateTo()//这是一个suspend函数,需要在协程中运行
不能用lifecycleScope.launch{}
- Compose的重组优化等等相关的特性,导致我们不能直接使用lifecycleScope.launch{}去启动一个协程。
- 如:
lifecycleScope.launch { //这里IDE会报警:Calls to launch should happen inside a LaunchedEffect and not composition
anim.animateTo()
}//意思很明确,launch一个协程,需要在LaunchedEffect中
- 区别: LaunchedEffect启动的协程,在Compose重组优化的过程中,是不会反复执行的,这样能够减少资源损耗。以及如果协程被反复执行,动画肯定也会出问题。
LaunchedEffect
- 允许我们在Compose的作用域中去启动一个不会在每次重组过程中都启动的协程。
- 同时,也支持我们传入某些参数,用来决定什么时候,在重组的过程中,去重新launch协程。
LaunchedEffect(Unit){//只看传入的参数在重组时有没有发生改变,改变则重启协程。
anim.animateTo()
}
animateTo
var scale by remember {
mutableStateOf(1.0f)//启动一个初始值为1.0f的scale
}
val anim = remember {
Animatable(scale)//初始的animatable时1.0f
}
LaunchedEffect(scale) {
anim.animateTo(scale)//当scale发生变化时,重启协程,将animatable,animateTo到scale当前值,也就是1.1f
}
Box(
modifier = Modifier
.width(700.dp)
.height(360.dp)
.scale(anim.value)
.clickable {
scale = if (scale == 1.0f) {//当点击的时候,切换scale的数值(接下来就能看到,反复点击,View会在1.1f和1.0f的scale倍数下,变换动画)
1.1f
} else {
1.0f
}
Toast
.makeText(
this@MainActivity,
"tap daily item",
Toast.LENGTH_LONG
)
.show()
}
) {
Text("code test for animatable")
}
snapTo
- animatable的animateTo,可以看到动画过程。
- 调用snapTo(),会立即生效到对应的targetState,没有动画过程。