本文主要是介绍手把手教你写 Compose 动画 -- 流程定制型动画 API:Animatable(),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
看看官方的解释:
Animatable 是一个值容器,它可以在通过 animateTo 更改值时为值添加动画效果。该 API 支持 animate*AsState 的实现。它可确保一致的连续性和互斥性,这意味着值变化始终是连续的,并且会取消任何正在播放的动画。
Animatable 的许多功能(包括 animateTo)以挂起函数的形式提供。这意味着,它们需要封装在适当的协程作用域内。例如,您可以使用 LaunchedEffect 可组合项针对指定键值的时长创建一个作用域。
反正我刚开始看这段解释有点懵。
老样子,代码引入一步步深入学习:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {val anim = Animatable()}}
}
注意:Animatable 导包的时候需要注意,不要选错:
抱歉,你这样写是会报错的:
很明显,Animatable 也需要用 remember 包起来:
提示我们需要加初始值,怎么填呢?我们可以看下 Animatable 的源码:
fun Animatable(initialValue: Float,visibilityThreshold: Float = Spring.DefaultDisplacementThreshold
)
需要一个 Float 类型的初始值:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {val anim = remember { Animatable(48f) }}}
}
但并不是不允许用 dp,我们可以这样写也能满足 Animatable 的要求:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {val anim = remember { Animatable(48.dp, Dp.VectorConverter) }}}
}
通过 Dp.VectorConverter
可以把 dp 转为 float。
接下来就可以配置动画了,直接调用 animateTo()
函数即可。
animateTo()
是个 suspend 函数,必须要在协程里面使用:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {val anim = remember { Animatable(48.dp, Dp.VectorConverter) }LaunchedEffect(Unit) {anim.animateTo()}}}
}
现在只需要在 animateTo()
里面添加目标值即可。
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {val anim = remember { Animatable(48.dp, Dp.VectorConverter) }LaunchedEffect(Unit) {anim.animateTo(96.dp)}}}
}
到这里 Animatable 就创建好了,现在我们就要可以用起来了:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)var big by mutableStateOf(false)setContent {val size = remember(big) { if (big) 96.dp else 48.dp }val anim = remember { Animatable(size, Dp.VectorConverter) }LaunchedEffect(big) {anim.animateTo(size)}Box(Modifier.size(anim.value).background(Color.Blue).clickable {big = !big})}}
}
让我解读下这段代码:
- Box 方块的 size 大小取决于 anim 的值,它的值会随着动画逐渐变化。
- 点击 Box 会改变 big 值,big 值变化会重新执行 LaunchedEffect 协程,animateTo 会执行,动画启动。
- big 从 false -> true,Box 动画由 48.dp -> 96.dp,big 从 true -> false,Box 动画由 96.dp -> 48.dp。
我们看下效果:
到这里,Animatable 的基本用法就讲完了。
不过 Animatable 还有个特别的功能,我们可以通过 snapTo() 定制动画的初始值。
例如下面的代码:
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)var big by mutableStateOf(false)setContent {val size = remember(big) { if (big) 96.dp else 48.dp }val anim = remember { Animatable(size, Dp.VectorConverter) }LaunchedEffect(big) {anim.snapTo(if (big) 192.dp else 0.dp)anim.animateTo(size)}Box(Modifier.size(anim.value).background(Color.Blue).clickable {big = !big})}}
}
我们添加了一句:anim.snapTo(if (big) 192.dp else 0.dp)
。
- Box 由小变大时,size 会瞬间到 0dp,然后从 0 -> 48dp
- Box 由大变小时,size 会瞬间到 192.dp,然后从 192.dp -> 96dp
看下效果:
这篇关于手把手教你写 Compose 动画 -- 流程定制型动画 API:Animatable()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!