compose动画全解(一)基础动画--AnimationSpec

基础动画规格 AnimationSpec

compose动画最基本的元素AnimationSpec,是compose动画的灵魂,定义了动画如何运动(物理曲线,持续时间,缓动效果等)。

分类

我个人分为两大类:基础动画和循环动画,基础动画包括物理模型的弹簧动画 和时间段的补间动画 ,关键帧动画 ,跳转动画 ;循环动画包含有限和无限 的,都是对时间动画的封装。 具体关系可以看AnimationSpec的继承关系图。


物理模型动画

SpringSpec 弹簧
定义:

使用提供的工厂函数spring构建

kotlin 复制代码
@Stable
public fun <T> spring(
    dampingRatio: Float = Spring.DampingRatioNoBouncy,
    stiffness: Float = Spring.StiffnessMedium,
    visibilityThreshold: T? = null
): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold)
参数:
  • dampingRatio : Float
    阻尼强度,越大越弹不动,1f无弹跳动画,0f无限次弹跳。
  • stiffness : Float
    弹性刚度,值越大,弹得越快。
  • visibilityThreshold: T? 动画提前结束的阈值,比如动画状态类型是Float,那么可以设置当目标达到0.1f时就认为动画可以结束了,默认是null。

持续时间动画

TweenSpec 补间动画
定义:

使用提供的工厂函数tween构建

kotlin 复制代码
@Stable
public fun <T> tween(
    durationMillis: Int = DefaultDurationMillis,
    delayMillis: Int = 0,
    easing: Easing = FastOutSlowInEasing
): TweenSpec<T> = TweenSpec(durationMillis, delayMillis, easing)
参数:
  • durationMillis: Int
    动画持续时间
  • delayMillis: Int
    动画延迟多久开始执行
  • easing: Easing
    缓动曲线,一般使用时间维度的贝塞尔曲线CubicBezierEasing。

可以在这个网站上看下贝塞尔曲线:贝塞尔曲线在线编辑

KeyframesSpec 关键帧动画

精确控制每一个时间点的动画,相比较tween,可以更精细的控制。

定义:
kotlin 复制代码
@Stable
public fun <T> keyframes(init: KeyframesSpecConfig<T>.() -> Unit): KeyframesSpec<T> {
    return KeyframesSpec(KeyframesSpecConfig<T>().apply(init))
}

参数是一个配置类,看起来比较麻烦,但是compose提供了三个中缀函数at,atFraction,using来传递参数,先看参数解释,再看下面的使用方式:

参数:
  • durationMillis: Int 动画持续时间
  • delayMillis: Int 动画延迟多久开始执行
  • <targetValue> at <time> using <Easing> 目标值 在时间点 使用缓动曲线
使用:
  1. 一维动画(类型就是Int,Float这种线性的变化)
kotlin 复制代码
keyframes<Int> {
    durationMillis = 3000
    delayMillis = 1000
    0 at 0 using LinearEasing //注意:缓动函数应用的是此帧到下一帧,而不是上一帧到此帧。
    100 atFraction 0.3f  //除了使用具体时间,还可以使用atFraction指定总时间的百分比
    200 at 2000
    ... ...
}
  1. 二维动画(类型是Offset这种位置的变化,x和y轴都会变)
kotlin 复制代码
keyframes<IntOffset> {
    durationMillis = 1000
    
    //Offset这种二维属性除了使用线性的时间缓动,还可以使用路径缓动ArcBelow设置移动的路径。
    IntOffset(0, 0) at 0 using LinearEasing using ArcBelow 

    IntOffset(0, 100) at 1000
}

Ps: ArcBelow只是简单的路径缓动(基于椭圆形),想要精细的控制移动的路径,需要使用PathEasing。

KeyframesWithSplineSpec 平滑的关键帧动画

相比较普通的关键帧动画,它使用了Monotone cubic Hermite spline这种插值算法来对帧节点之间的过渡做平滑处理,普通的关键帧动画使用的是线性插值,意味着在帧节点可能因为设置的变化过大出现突变,但是keyframesWithSplineSpec会自动对帧节点的过渡平滑处理,一定不会出现突变。

periodicBias参数

KeyframesWithSplineSpec有一个重载函数,多了一个periodicBias参数, 这个参数的作用是循环动画中为了实现首尾速度一致(周期性速度连续性),优先修改起始切线速度还是结束切线速度的权重。

compose的注解是一句话:A value from 0f to 1f, indicating how much the starting or ending velocities are modified respectively to achieve periodicity.

详细理解:

  • 速度(Velocity): 在动画中,"速度"可以理解为动画值变化的快慢,对应到样条曲线上就是切线的斜率。斜率越大,变化越快。

  • 周期性(Periodicity): 指的是动画从头到尾播放完后,能够平滑地衔接回开头,形成一个无缝的循环。为了实现这一点,动画结束时的"出速度"应该和开始时的"入速度"相等。

  • 偏向(Bias): periodicBias 就是一个"偏向"或"权重"值。它决定了在多大程度上为了"周期性"而去修改首尾的速度。

那么0f就是完全不考虑周期性,1f就是完全考虑周期性,会让首尾的动画连贯起来。

定义:
kotlin 复制代码
public fun <T> keyframesWithSpline(
    init: KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>.() -> Unit
): KeyframesWithSplineSpec<T> =
    KeyframesWithSplineSpec(
        config = KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>().apply(init)
    )

public fun <T> keyframesWithSpline(
    @FloatRange(0.0, 1.0) periodicBias: Float,
    init: KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>.() -> Unit
): KeyframesWithSplineSpec<T> =
    KeyframesWithSplineSpec(
        config = KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>().apply(init),
        periodicBias = periodicBias,
    )
使用:

跟前面的KeyframesSpec 一样的使用方式,用到中缀函数传递参数。

kotlin 复制代码
keyframesWithSpline(periodicBias = 0.5f) {
	durationMillis = 2000
	1f at 1000 using LinearEasing
},
SnapSpec 跳转动画

这个很简单,无中间过程,立刻跳转到目标值。

定义:
kotlin 复制代码
@Stable public fun <T> snap(delayMillis: Int = 0): SnapSpec<T> = SnapSpec<T>(delayMillis)
ArcAnimationSpec 路径动画

这还是一个试验性质的动画(当前使用的动画版本是1.8.2),主要用于二维移动的路径控制,走一个漂亮弧形。还没有工厂函数提供出来,其中路径模式就是前面关键帧动画使用的ArcMode,其他都是见过的,没啥可讲的,后续版本可能有更多的功能设计。

定义:
kotlin 复制代码
@ExperimentalAnimationSpecApi
@Immutable
public class ArcAnimationSpec<T>(
    public val mode: ArcMode = ArcBelow,
    public val durationMillis: Int = DefaultDurationMillis,
    public val delayMillis: Int = 0,
    public val easing: Easing = FastOutSlowInEasing // Same default as tween()
) : DurationBasedAnimationSpec<T>

重复动画

重复动画已经不是最基础的动画了,是对时间动画的封装使用。

RepeatableSpec 有限动画
定义:
kotlin 复制代码
@Stable
public fun <T> repeatable(
    iterations: Int,
    animation: DurationBasedAnimationSpec<T>,
    repeatMode: RepeatMode = RepeatMode.Restart,
    initialStartOffset: StartOffset = StartOffset(0)
): RepeatableSpec<T> = RepeatableSpec(iterations, animation, repeatMode, initialStartOffset)
参数:
  • iterations: Int
    重复次数
  • animation: DurationBasedAnimationSpec
    时间基础动画
  • repeatMode: RepeatMode
    重复模式(Restart/Reverse)
  • initialStartOffset: StartOffset
    开始动画偏移量,传入偏移时间和偏移类型,类型包括Delay/FastForward

偏移类型的Delay就是等待一段时间后才开始下一轮动画,FastForward意思是下一轮的动画直接从传入的时间点开始,也就是提前执行。

InfiniteRepeatableSpec 无限动画
定义:

和有限动画的区别就是少了重复次数,其他一样的。

kotlin 复制代码
@Stable
public fun <T> infiniteRepeatable(
    animation: DurationBasedAnimationSpec<T>,
    repeatMode: RepeatMode = RepeatMode.Restart,
    initialStartOffset: StartOffset = StartOffset(0)
): InfiniteRepeatableSpec<T> = InfiniteRepeatableSpec(animation, repeatMode, initialStartOffset)

这篇文章学习了compose的所有基础动画,但是没有应用,下篇开始最基本的应用,就可以用代码展现动画效果了,喜欢我的文章请点赞收藏:)

相关推荐
千里马学框架4 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台4 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone4 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc4 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo4 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077004 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼4 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone4 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen4 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone4 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui