Jetpack Compose - AnimationSpec (七)

回弹效果的简单实现

本文需要之前JC教程的 第六课作为基础,没看的 先看下之前的第六课

可以参考如下代码:

LaunchedEffect(change) {
    anim.animateTo(size, spring(Spring.DampingRatioHighBouncy))
}

先看下效果吧

回弹.gif

这里的spring 是弹簧的意思

image.png

我们可以看下 这里spring的函数 返回的是一个SpringSpec的对象

image.png

他实际上就是 AnimationSpec这个接口的一个实现

image.png

可以看下 这个接口有多少种默认的实现 即可知道 compose 为我们提供了哪些便利

image.png

再回过头来看这个animateTo 函数 其实也是需要AnimationSpec这个参数的

image.png

当然你不传这个参数的话 就是默认参数 默认情况下 看下代码是没有任何回弹效果的

image.png

可以看下继承关系树 image.png

TweenSpec

image.png

首先看下构造函数,第一个 参数代表动画的执行时间,第二个参数代表动画延迟多少ms 执行,

第三个最重要,第三个代表动画的执行 曲线,啥意思?其实就是 以前属性动画中的interpolator

讲白了 一个view 坐标0 移动到 坐标100 有多种速度的移动方式

image.png

这里提供了4种方式:

FastOutSlowInEasing 一开始快 后面慢


LinearOutSlowInEasing  越来越慢 


FastOutLinearInEasing 越来越快


LinearEasing 匀速



肯定是够用了, 如果不够用 自定义也很简单,自己实现一个Easing即可

所以其实TweenSpec 是Compose中最简单的Spec了,很基础。

TweenSpec的使用场景 主要就是: 开始和结束的状态是确定的,变化的只有 状态变化的这个过程。

SnapSpec

这个太简单了,就是个延时执行动画的东西,我其实也不知道为啥要起这个snap的名字,

LaunchedEffect(change) {
    anim.animateTo(size, snap(1000))
}

image.png

KeyframeSpec

setContent {
    val size = remember(change) {
        if (change) 50.dp else 100.dp
    }
    val anim = remember { Animatable(size, Dp.VectorConverter) }
    LaunchedEffect(change) {
        anim.animateTo(size, keyframes {
            200.dp at 150
        })
    }

    Row {

        Box(
            Modifier
                .size(anim.value)
                .background(Color.Red)
                .clickable {
                    change = !change
                }) {

        }
    }
}

前面我们介绍过,动画默认的执行时间是300ms,这个keyframe 其实就是关键帧的意思,你可以设置 在多少ms这个时间点内 view的状态是如何,比如上述的例子就是在150ms的时候 大小变成了200.dp

关键帧的参数其实挺多的,

大部分的参数其实都可以直接看注释 看明白, image.png

我们唯一要注意的就是下面的 两个函数

image.png

这个infix是啥意思?竟然还是个关键字? 代表了叫中缀函数 他的作用其实就是

方便你的写法, 可以参考上文 200.dp at 150 这种写法。自己体会下 不难理解

另外总结下,snapspec 以及 tweenspec 还有这个keyframespec 你可以发现 他们的效果都是和时间 强相关的

这也就是为什么 这3个spec 都在 DurationBasedAnimationSpec 之下

image.png

RepeatableSpec

顾名思义重复执行动画

LaunchedEffect(change) {
    anim.animateTo(size, repeatable(3, tween()))
}

image.png

但是要注意了这里的spec类型只接受 DurationBasedAnimationSpec

另外这里最后一个参数 是设置偏移量的, 很多人会觉得奇怪 一个偏移量为啥不直接弄个参数值。还要搞个对象呢?

image.png

其实主要区别就在这里,一个是动画延迟多久执行,另外一个是直接快进到哪个时间点的状态再开始执行

image.png

另外就是还有一个 InfiniteRepeatableSpec 顾名思义 这个就是无限执行动画的 他会一直执行下去

LaunchedEffect(change) {
    anim.animateTo(size, infiniteRepeatable( tween(),
        initialStartOffset = StartOffset(300, StartOffsetType.FastForward))
    )
}

有人就要问了,那怎么让他退出呢?

让这个协程退出就行了啊,那么怎么让这个协程退出呢

其实思路很简单,在recompose的时候 不要执行他就行了 协程 自动就会退出了

image.png

本质上就是找个机会 比如点击事件的时候 改变这个animateState的值 这样recompose的时候 这个协程就退出了

猜你喜欢

转载自juejin.im/post/7114489007538438158