Android Compose 动画配置之RepeatableSpec、InfiniteRepeatableSpec
本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
前言前面用三篇文章分别介绍了 Compose 动画规格的TweenSpec(补间动画配置)、SnapSpec(快闪动画配置)、KeyframesSpec(关键帧动画配置)和SpringSpec(弹簧动画配置),本篇将继续介绍 Compose 动画规格的最后两个配置:RepeatableSpec(重复动画配置)、InfiniteRepeatableSpec(无限重复动画配置)
RepeatableSpecRepeatableSpec顾名思义是重复配置的意思,可以让动画进行重复执行,定义如下:
classRepeatableSpec(
valiterations:Int,
valanimation:DurationBasedAnimationSpec,
valrepeatMode:RepeatMode=RepeatMode.Restart,
valinitialStartOffset:StartOffset=StartOffset(0)
):FiniteAnimationSpec
RepeatableSpec构造方法有四个参数,对应参数解析如下:
iterations:重复次数,即让动画重复执行多少次,必填参数animation:重复执行的目标动画配置,必填参数repeatMode:重复模式,有两种可选模式:重新播放、反向播放,默认为重新播放initialStartOffset:初始启动偏移,偏移的对象是动画时间,默认为StartOffset(0)即不偏移除了直接使用RepeatableSpec构造函数创建RepeatableSpec外,Compose 同样为我们提供了简便函数repeatable让开发者使用,参数与构造函数参数一致,下面就详细介绍各个参数的使用和效果。
iterationsiterations是RepeatableSpec必填参数之一,是动画重复执行的次数,很好理解,就是我们想让动画重复执行多少次,那么这个参数就传多少就行了,注意类型为 Int 类型,即只能为整数,如我们想让动画重复执行 5 次,代码使用如下:
valrepeatableSpec=repeatable(iterations=5,animation=...)
animationanimation也是RepeatableSpec必填参数之一,是重复执行的目标动画配置,即我们要对那个动画配置进行重复执行。
通过RepeatableSpec的定义发现animation是DurationBasedAnimationSpec类型,还记得在开始介绍动画配置时的那张继承关系图么?再来看一下:
DurationBasedAnimationSpec只有三个实现子类,也就是我们最开始介绍的三个动画配置:TweenSpec(补间动画配置)、SnapSpec(快闪动画配置)、KeyframesSpec(关键帧动画配置)。
也就是说animation参数我们只能传TweenSpec、SnapSpec、KeyframesSpec这三种动画配置对象,而上一篇介绍的SpringSpec(弹簧动画配置)、 现在正在介绍的RepeatableSpec本身以及后面介绍的InfiniteRepeatableSpec(无限重复动画配置)都不能用于RepeatableSpec进行重复执行。
我们还是以我们最熟悉的方块动画来体验一下RepeatableSpec的使用效果,代码如下:
varmoveToRightbyremember{mutableStateOf(false)}
valtargetValue=if(moveToRight)200.dpelse10.dp
//补间动画
valanimation1=tween(durationMillis=500)
//快闪动画
valanimation2=snap()
//关键帧动画
valanimation3=keyframes{
50.dpat150withFastOutSlowInEasing
150.dpat200
}
//添加重复配置,重复次数三次
valstartPadding1byanimateDpAsState(targetValue,animationSpec=repeatable(3,animation1))
valstartPadding2byanimateDpAsState(targetValue,animationSpec=repeatable(3,animation2))
valstartPadding3byanimateDpAsState(targetValue,animationSpec=repeatable(3,animation3))
Column{
//应用重复补间动画
Text("RepeatableSpec--TweenSpec",modifier=Modifier.padding(top=20.dp,start=10.dp))
Box(
Modifier
.padding(start=startPadding1,top=10.dp,bottom=10.dp)
.size(100.dp)
.background(Color.Blue)
.clickable{
moveToRight=!moveToRight
}
)
//应用重复快闪动画
Text("RepeatableSpec--SnapSpec",modifier=Modifier.padding(top=20.dp,start=10.dp))
Box(
Modifier
.padding(start=startPadding2,top=10.dp,bottom=10.dp)
.size(100.dp)
.background(Color.Blue)
.clickable{
moveToRight=!moveToRight
}
)
//应用重复关键帧动画
Text("RepeatableSpec--KeyframesSpec",modifier=Modifier.padding(top=20.dp,start=10.dp))
Box(
Modifier
.padding(start=startPadding3,top=10.dp)
.size(100.dp)
.background(Color.Blue)
.clickable{
moveToRight=!moveToRight
}
)
}
创建三个方块,使用RepeatableSpec分别作用于TweenSpec、SnapSpec、KeyframesSpec运行一下看看效果:
作用于TweenSpec和KeyframesSpec的动画效果很明显,肉眼可见的确实重复执行了 3 次,但是中间的SnapSpec动画怎么好像只执行了一次呢?这是因为SnapSpec的特性,前面文章我们介绍了SnapSpec的动画时间是 0,所以无论重复执行多少次动画总时间还是 0,所以动画效果都是一瞬间执行完成了,看着像只执行了一次。
repeatModerepeatMode是重复模式,值是枚举类型RepeatMode,有两个枚举值:Restart重新播放和Reverse反向播放,定义如下:
enumclassRepeatMode{
//重新播放
Restart,
//反向播放
Reverse
}
以TweenSpec为例看一下使用效果:
valspec=repeatable(3,animation,repeatMode=RepeatMode.Restart)
valsepc2=repeatable(3,animation,repeatMode=RepeatMode.Reverse)
对同一个动画重复 3 次,重复模式分别设置Restart和Reverse,看一下运行效果:
可以发现区别还是很明显的,使用Restart模式时在每次执行完后会瞬间回到起点再重新执行,效果就会很突兀;而使用Reverse模式时,在每次执行完后会反向执行,视觉体验会好很多。当然开发中应根据实际需求设置对应的重复模式。
需要注意的是在使用Reverse反向模式且重复次数为双数时,动画运行效果可能不符合预期,还是上面的例子将重复次数从 3 修改为 2 看一下运行效果:
valsepc2=repeatable(2,animation,repeatMode=RepeatMode.Reverse)
可以发现,因为重复次数设置的 2 ,所以动画会从起点运动到目标位置,然后再从目标位置反向回到起点,到这里是符合预期的,但是在动画最后一瞬间又直接回到的目标位置,看起来就比较突兀,按照正常逻辑重复次数设置为 2 那动画应该停在起点才对,这是为什么呢?
这是因为我们使用的是animateXxxAsState动画,他的作用就是将对象以动画形式运动到目标点,而我们之前介绍的包括RepeatableSpec在内的动画配置都是对动画进行修饰的,他们只能改变动画的过程而不能改变动画的结果,所以上面的动画最后会瞬间回到目标终点。
在使用RepeatableSpec且重复模式设置为Reverse时,需要注意重复次数设置为双数是否符合你的预期。
initialStartOffsetinitialStartOffset是初始启动偏移,可以设置动画偏移一定的动画时长,值为StartOffset类型。
StartOffset构造方法有两个参数:
offsetMillis:偏移的动画时间,单位毫秒offsetType:偏移类型,有两个可选值:
Delay:延迟启动,即等待offsetMillis时长后再启动动画,是offsetType的默认值FastForward:快进启动,即跳过动画的offsetMillis时长,再执行后面的动画需要注意的是initialStartOffset针对的是整个动画的时长做偏移而不是每次重复的动画做偏移。
比如单个动画时长为 300ms ,重复执行 3 次,那整个动画时长为 900ms,offsetMillis设置 300ms,offsetType设置不同的类型时动画表现不一样,如下:
offsetType使用Delay时,整个动画时长为offsetMillis( 300ms )+ 900ms = 1200msoffsetType使用FastForward时,动画时长为 900ms -offsetMillis( 300ms ) = 600ms代码及效果如下:
valspec=repeatable(3,animation,repeatMode=RepeatMode.Reverse,initialStartOffset=StartOffset(300,StartOffsetType.Delay))
valspec2=repeatable(3,animation,repeatMode=RepeatMode.Reverse,initialStartOffset=StartOffset(300,StartOffsetType.FastForward))
当为Delay时动画延迟了 300ms 后执行,且重复执行了 3 次;而当为FastForward时,动画是立即执行,但是因为设置的offsetMillis为 300ms ,且单次动画时长也为 300ms,所以动画跳过了第一次动画直接到达了终点,然后再重复执行了 2 次。
InfiniteRepeatableSpecInfiniteRepeatableSpec是无限重复动画,即无限循环动画,使用方式与参数基本与RepeatableSpec相同,唯一的区别是少一个iterations参数,因为是无限重复所以不需要设置重复次数。
除了构造方法以外 Compose 同样提供了简便函数infiniteRepeatable供开发者使用,使用如下:
valspec=infiniteRepeatable(animation,repeatMode=RepeatMode.Reverse,initialStartOffset=StartOffset(300,StartOffsetType.Delay))
valstartPadding1byanimateDpAsState(targetValue,animationSpec=)
效果如下:
启动后动画会无限重复的播放。
那如果我们想停止无限重复播放怎么办呢?可以修改动画状态然后根据状态对动画重新设置一个 Spec,比如上面的动画当 moveToRight 为 false 时将 animationSpec 设置为SnapSpec就可以停止动画了,代码如下:
//动画状态
varmoveToRightbyremember{mutableStateOf(false)}
valtargetValue=if(moveToRight)200.dpelse10.dp
//无限重复动画配置
valinfiniteRepeatableSpec=infiniteRepeatable(
tween(),
repeatMode=RepeatMode.Reverse,
initialStartOffset=StartOffset(300,StartOffsetType.Delay)
)
//根据状态设置动画配置,当moveToRight为false时设置snap
valanimationSpec=if(moveToRight)infiniteRepeatableSpecelsesnap()
valstartPaddingbyanimateDpAsState(
targetValue,
animationSpec=animationSpec
)
Column{
Box(
Modifier
.padding(start=startPadding,top=20.dp,bottom=10.dp)
.size(100.dp)
.background(Color.Blue)
)
//添加按钮改变moveToRight值
Button(
onClick={moveToRight=!moveToRight},
modifier=Modifier.padding(start=10.dp)
){
Text(if(moveToRight)"停止"else"开始")
}
}
运行效果如下:
这样就实现了手动停止无限循环动画的功能。
最后本篇详细介绍了RepeatableSpec(重复动画配置)、InfiniteRepeatableSpec(无限重复动画配置)的详细配置使用并展示了不同配置呈现的效果, 至此关于 Compose 动画的六种配置我们就介绍完了,从下一篇开始我们继续探索 Compose 动画更深入的使用,请持续关注本专栏了解更多 Compose 动画相关内容。
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线