您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
iOS UIView动画实践(五):Keyframe Animation
 
作者:付宇轩 来源:CSDN 发布于: 2015-08-03
  1601  次浏览      34
 

摘要:本文为iOS UIView动画实践系列第五篇。详细介绍Keyframe动画是如何帮助开发者有效地拆分由若干段动画连接而成的复杂动画,并较为精准地定义每段动画的起始点及持续时间,也让代码组织方面变得非常清晰。

前言

有些时候大家可能会遇到制作复杂、具有连贯性UIView动画的需求,这时大家可能会使用在completion闭包中衔接一段一段的动画,使之成为一段连续的动画。

如果我们只是连接2个,或者3个动画,这种方式或许还行得通,但如果有更多的动画片段需要连接的时候,这种方式会带来灾难性的问题,你的代码会非常的冗余,不断的在completion闭包中嵌套代码,使代码维护起来相当的困难。所以今天向大家介绍能更好地实现这个需求的方法,Keyframe动画。

Keyframe动画可以让我们有效的拆分由若干段动画连接而成的复杂动画,可以较为精准的定义每段动画的起始点及持续时间,并且在代码组织方面也非常清晰。先看看今天要带大家实现的动画Demo:

使用场景

我们先来认识一下,在什么样的场景下需要使用Keyframe动画。如图下所示,这是一个由四段动画组成的一个复杂动画,让UIView沿着长方形的轨迹运动:

我们来看看用代码如何实现:

UIView.animateWithDuration(1, animations: {  
view.center.x += 200.0
}, completion: { _ in
UIView.animateWithDuration(1, animations: {
view.center.y += 100.0
}, completion: { _ in
UIView.animateWithDuration(1, animations: {
view.center.x -= 200.0
}, completion: { _ in
UIView.animateWithDuration(1, animations: {
view.center.y -= 100.0
}, completion: nil)
})
})
})

通过上面的伪代码可以看到,我们使用了completion闭包的方式连接每一段的动画,代码看起来尚且算清晰,可读性也马马虎虎。但是大家想象一下,如果我们使UIView按照一个复杂的路线运行,这一段动画可能有十几、几十段动画组成的,那么如果再使用completion闭包这种方式连接,那代码是多么的惨不忍睹。幸好我们有Keyframe动画,下面就让我们来看看如何使用Keyframe动画。

Keyframe动画

首先我们会使用到UIView的另一个动画方法animateKeyframesWithDuration(_: delay: options: animations: completion: ) :

UIView.animateKeyframesWithDuration(2, delay: 0, options: [], animations: {  
// add keyframes
}, completion: nil)

这个方法的几个参数与前几个使用过的动画方法参数一样。上面代码片段的意思是整个关键帧动画的持续时间为2秒、无延迟、无动画选项、执行完毕后无后续执行的代码。

注:该方法的动画选项不再是UIViewAnimationOptions,而是UIViewKeyframeAnimationOptions。具体的内容大家可以去查阅Apple的文档。

接下来我们要在animations闭包中添加关键帧了:

UIView.animateKeyframesWithDuration(2, delay: 0, options: [], animations: {  
UIView.addKeyframeWithRelativeStartTime(0,
relativeDuration: 0.25, animations: {
view.center.x += 200.0
})
}, completion: nil)

addKeyframeWithRelativeStartTime(_: relativeDuration: animations: )是UIView添加关键帧的方法,该方法有三个参数:

  • startTime:关键帧开始时间,该时间是相对整个关键帧动画持续时间的相对时间,一般值在0到1之间。如果为0,则表明这一关键帧从整个动画的第0秒开始执行,如果设为0.5,则表明从整个动画的中间开始执行。
  • relativeDuration:关键帧持续时间,该时间同样是相对整个关键帧动画持续时间的相对时间,一般值也在0到1之间。如果设为0.25,则表明这一关键帧的持续时间为整个动画持续时间的四分之一。
  • animations:设置视图动画属性的动画闭包。

我们解释一下上面这段代码。整个关键帧动画的持续时间为2秒,第一个关键帧从第0秒开始,运行0.5秒结束。下面我们完成其他三个关键帧:

UIView.animateKeyframesWithDuration(2, delay: 0, options: [], animations: {  
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration:
0.25, animations: {
view.center.x += 200.0
})
UIView.addKeyframeWithRelativeStartTime(0.25, relativeDuration:
0.25, animations: {
view.center.y += 100.0
})
UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration:
0.25, animations: {
view.center.x -= 200.0
})
UIView.addKeyframeWithRelativeStartTime(0.75, relativeDuration:
0.25, animations: {
view.center.y -= 100.0
})
}, completion: nil)

第二个关键帧的开始时间为0.25,也就是从整个动画时间的第0.5时开始执行,同样持续0.5秒。后两个关键帧的参数就不难理解了。

现在整个代码看起来非常整洁,条理清晰,可读性非常好,而且可以有更精确的控制。即使再多几个关键帧也同样可以从容应对。

关键帧动画不仅仅用于同一个视图的分段动画,也可使使用于不同视图的组合动画,由于我们还没讲到图层动画,所以,开篇的示例动画中就使用了关键帧动画实现了多个视图的组合动画。

示例动画

在这个示例中虽然看起来是一个纸飞机视图的连续动画,但其实是由三个纸飞机视图组合而成的:

从图中可以看到其实是有三个纸飞机视图,只不过在界面加载之前2号和3号纸飞机视图的透明度都是为零。

整个动画是由这三个纸飞机视图通过关键帧动画组合而成:

图中标示出了三个飞机视图的运行轨迹、视图大小、视图透明度的状态,我们来看看代码如何实现:

let zoomInScaleTransform = CGAffineTransformMakeScale(0.2, 0.2)  
UIView.animateKeyframesWithDuration(3, delay: 0, options:
[], animations: {
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration:
0.2, animations: {
self.customHeaderView.paperAirplane.center.x
+= self.view.frame.width
self.customHeaderView.paperAirplane.center.y
+= -180
self.customHeaderView.paperAirplane.transform
= zoomInScaleTransform
})
UIView.addKeyframeWithRelativeStartTime(0.3, relativeDuration:
0.01, animations: {
self.customHeaderView.paperAirplaneOpposite.alpha = 1
self.customHeaderView.paperAirplaneOpposite.transform
= zoomInScaleTransform
})
UIView.addKeyframeWithRelativeStartTime(0.3, relativeDuration:
0.5, animations: {
self.customHeaderView.paperAirplaneOpposite.transform =
CGAffineTransformIdentity
self.customHeaderView.paperAirplaneOpposite.center.x -=
self.view.frame.width
self.customHeaderView.paperAirplaneOpposite.center.y +=
90
})
UIView.addKeyframeWithRelativeStartTime(0.9,
relativeDuration: 0.01, animations: {
self.customHeaderView.paperAirplaneComeBack.
alpha = 1
})
UIView.addKeyframeWithRelativeStartTime(0.9,
relativeDuration: 0.2, animations: {
self.customHeaderView.paperAirplaneComeBack.
center.x += 33
})
}, completion: { _ in
self.restorePaperAirplaneStatus()
})

大家看到这大家可能会有疑问了,三段动画怎么会有五个关键帧呢,我们来刨析一下:

  • 第一个关键帧:完成1号纸飞机视图运动到右上角并移出屏幕,视图逐渐变小的动画。该关键帧从整个动画的第0秒开始执行,持续时间为0.6秒。
  • 第二个关键帧:由于2号纸飞机视图的初始透明度为零,所以在第二个关键帧将透明度设为1,并且缩小视图。注意这两个动作需要在瞬间完成,所以relativeDuration设为0.01,一个极短的时间。开始时间为整个动画的第0.9秒开始,较第一个关键帧延迟0.3秒。
  • 第三个关键帧:与第二个关键帧同时开始执行,完成2号纸飞机视图从小变大、并且往左下角运动,一直移出屏幕。持续时间为1.5秒。
  • 第四个关键帧:与第二个关键帧作用相似,改变3号纸飞机视图的透明度,同样是在瞬间完成。
  • 第五个关键帧:与第四个关键帧同时执行, 完成向右移动的动画,持续0.6秒。

关键帧完成之后,在completion闭包中调用restorePaperAirplaneStatus()方法,恢复3个纸飞机视图的状态及位置,以便再次执行动画。

总结

大家在使用关键帧动画时,对于关键帧的开始时间和持续时间需要仔细设置,保证每个关键帧在合适的时间开始,执行恰当的持续时间。在必要时候也需要在关键帧里修改视图的一些状态,但要设置极短的持续时间,表示瞬间完成。

   
1601 次浏览       34
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新活动计划
嵌入式软件架构设计 12-11[北京]
LLM大模型与智能体开发实战 12-18[北京]
嵌入式软件测试 12-25[北京]
AI原生应用的微服务架构 1-9[北京]
AI大模型编写高质量代码 1-14[北京]
需求分析与管理 1-22[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...