iOS 平台下酷炫而流畅的动画效果着实值得标榜,恰当的时机加入动画效果可以极大的提升用户体验。
iOS 平台的动画,按照层次可以分为:
- UIView Animation
- Core Animation
这篇文章我们先介绍 UIView Animation。
UIView Animation 存在于上图中蓝色的层,其实就是对下层 Core Animation 的封装,可以理解为轻量级的动画处理类。而Core Animation 即对应图中的 Core Animation。
UIView Animation 简介
科普向,如果对基本的方法和属性很了解的话请直接跳到下一节实战
我们可以轻松的使用 UIView 中的方法来设置简单的动画,如:
animateWithDuration()
transitionFromView()
animateKeyframesWithDuration()
这些方法的参数很类似,比较常用的有:
-
duration
动画持续的时间 -
delay
延迟播放动画的时间 -
options
动画的播放类型 -
animations
闭包,动画的实质内容 -
completion
闭包,动画执行完毕后触发,可为nil
options 的值用来设置动画的速度曲线,可以是:
- .CurveEaseInOut // 慢进慢出(默认值)
- .CurveEaseIn // 慢进
- .CurveEaseOut // 慢出
- .CurveLinear // 匀速
如果使用的是 transitionFromView()
方法,那么 options 的值可以设置转换的方向和方式。由于 UIView Animation 的封装程度很高,动画播放的方式几乎都可以在这个 options 方法中进行设置。
拉伸动画
UIView Animation 最常见的应用就是对控件的 Constrain 的变化实施动画特效。
** 第一步:在 StoryBoard 中找到并选中目标控件的 Constraint **
也可以在左边的文件结构中选中目标 Constraint:
** 第二步:打开辅助编辑器,将 Constraint 关联到 ViewController 中**
完毕后,Constraint 作为属性出现在 ViewController 中:
** 第三步:改变 Constraint 并设置动画**
我们知道每一个 Constrant 都有两个属性,一个是 multiplier ,另一个是 constant。这里我们只调整 constant:
// 重新设置该 Constraint 的 constant 值为320(原为160)
imageHeight.constant = 320.0
// 设置动画,持续时间0.5秒,0秒延迟,默认速度
UIView.animateWithDuration(0.5, delay: 0, options: .CurveEaseInOut, animations: {
// 调用 image 控件的 layoutIfNeeded() 方法来重新布局
self.image.layoutIfNeeded()
}, completion: nil)
以上是对 Constraint 的 constant 的改变设置动画,那如果是 multiplier 属性呢?
很不幸,Constraint 的 multiplier 属性是 Read-Only 的,所以如果要设置 Constraint 的 multiplier 属性,我们需要把原有的 Constraint 剔除,然后重新定义一个新的 Constraint 并加入到约束集合中。
第一步:为目标 Constraint 设置 Identifier
由于目标控件可能含有很多的 Constraint ,所以我们需要为目标 Constraint 设置 Identifier,以便我们在代码中可以找到它。
选中控件,在属性检查器中找到目标 Constraint:
双击目标 Constraint 进入到下级界面:
在这里我们为目标 Constaint 设置 Identifier
第二步:遍历 Constraints ,替换目标 Constraint
// 定义一个新的 Constaint
let newConstraint = NSLayoutConstraint(item: image, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 2.0, constant: 0)
// 遍历所有 Constraint 找出目标 Constraint
for c in image.constraints {
if c.identifier == "BlaBlaBla" {
// 删除旧的 Constraint
image.removeConstraint(c)
// 添加新的 Constraint
image.addConstraint(newConstraint)
}
}
弹簧动画
弹簧动画(Duang~~~)其实没啥新鲜的,只是在拉伸动画方法的基础上添加了两个属性而已。usingSpringWithDamping
是弹簧的弹力系数,initialSpringVelocity
是弹簧的初始速度。
func animateWithDuration(
duration: NSTimeInterval,
delay: NSTimeInterval,
usingSpringWithDamping dampingRatio: CGFloat,
initialSpringVelocity velocity: CGFloat,
options: UIViewAnimationOptions,
animations:{
// 拉伸动画
},
completion: nil)
过渡动画
过渡动画就是 Transition Animation,控件只有在以下三种语句被执行时,才可以使用过渡动画:
- 改变 hidden 属性
- addSubview()
- removeFromSuperview()
下面我们定义一个过渡动画:
UIView.transitionWithView(imageView,
duration: 0.3,
options: .TransitionFlipFromLeft, // 可选值
animations: {
imageView.hidden = true
},
completion: {_ in
imageView.removeFromSuperview()
}
)
动画的内容就是 imageView 消失,但是只设置 hidden 属性是不够的。还要在动画结束后使其在父视图中移除。
变换动画
变换动画就是 Affine Transform Animation,动画中对控件进行旋转、伸缩等变换:
UIView.animateWithDuration(0.5, delay: 0.0,
options: .CurveEaseOut,
animations: {
//两个参数分别为 x、y 轴方向上的伸缩倍数
imageView.transform = CGAffineTransformMakeScale(5.0, 10.0)
// 对控件进行旋转
imageView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
}, completion: nil)
关键帧动画
关键帧动画通常用来制作较为复杂的动画,可以把一个动画过程分割为几个阶段。
第一个参数,startTime
是一个0~1的数,代表着开始时间占动画总时间的百分比。
第二个参数,relativeDuration
也是一个0~1的数,代表着持续时间占总时间的百分比。
UIView.animateKeyframesWithDuration(2.0, delay: 0.0, options: [], animations: {
UIView.addKeyframeWithRelativeStartTime(0.25, relativeDuration: 0.1, animations: {
// 第一阶段的动画
})
UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration: 0.1, animations: {
// 第二阶段的动画
})
UIView.addKeyframeWithRelativeStartTime(0.75, relativeDuration: 0.8, animations: {
// 第三阶段的动画
})
}, completion: nil)