目前在 UIKit 至少有三种创建动画的方法。iOS 4 之前的 begin/commit 方式,以及在 iOS 4 中引入的 block 方式。在 iOS 10 发布的时候,UIKit 新增了一个创建动画的专用类 UIViewPropertyAnimator,在 iOS 11 中这个类也新增了一些属性。下面我们来比较一下用 block 创建动画和用 UIViewPropertyAnimator 的区别。
基本动画
最简单的动画,只改动 View 的一个属性,用 block 方式实现:
[UIView animateWithDuration:1.0 animations:^{
self.view.backgroundColor = UIColor.redColor;
}];
UIViewPropertyAnimator
有一个最接近上面的创建方式:
[UIViewPropertyAnimator runningPropertyAnimatorWithDuration:1.0 delay:0.0 options:kNilOptions animations:^{
self.view.backgroundColor = UIColor.redColor;
} completion:nil];
动画的时间曲线
使用 block 创建动画,如果要改变默认的时间曲线,只需要给 UIViewAnimationOptions
赋对应的值即可:
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
} completion:nil];
UIViewPropertyAnimator
也接受 UIViewAnimationOptions
作为参数,但是不是所有的 option
都会生效,transition
相关的以及控制动画重复的 repeat
和自动翻转的 autoreverse
类的 option
会被忽略:
[UIViewPropertyAnimator runningPropertyAnimatorWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
} completion:nil];
除了上面的方法,我们也可以使用初始化方法创建,但是这种方式初始化的 animator
不会立即开始,需要主动开启:
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0 curve:UIViewAnimationCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
}];
[animator startAnimation];
注意这里的 curve
参数是 UIViewAnimationCurve
枚举,只支持 Linear, EaseIn, EaseOut, EaseInOut
四种曲线。
动画开始时间延迟
使用 block 创建动画,接口有可以控制延迟的 delay 参数:
[UIView animateWithDuration:1.0 delay:3.0 options:UIViewAnimationOptionCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
} completion:nil];
UIViewPropertyAnimator
的 +runningPropertyAnimatorWithDuration:delay:options:animations:completion:
方法也有 delay 参数可以控制动画延迟。但是如果是用初始化方法创建的 UIViewPropertyAnimator
也是可以控制延迟的:
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0 curve:UIViewAnimationCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
}];
[animator startAnimationAfterDelay:3.0];
动画结束的回调
使用 block 创建动画,接口提供了一个可以在动画结束时执行任务的回调:
[UIView animateWithDuration:1.0 delay:3.0 options:UIViewAnimationOptionCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
} completion:^{
NSLog(@"Animation Finished");
}];
对于 UIViewPropertyAnimator
,你可以添加任意多个结束回调,回调的 block
有一个参数 UIViewAnimatingPosition
用来标记动画结束时 View 的状态,Start
表示恢复到动画前的状态,Current
表示结束动画时,停在了当前态,End
表示动画停在了结束态:
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:1.0 curve:UIViewAnimationCurveLinear animations:^{
self.view.backgroundColor = UIColor.redColor;
}];
[animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
if (finalPosition == UIViewAnimatingPositionEnd) {
NSLog(@"First Completion");
}
}];
[animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
if (finalPosition == UIViewAnimatingPositionEnd) {
NSLog(@"Second Completion");
}
}];
[animator startAnimation];