在iOS 10之前校翔,執(zhí)行動(dòng)畫(huà)可以使用UIView
以下三個(gè)類(lèi)方法:
animateWithDuration: animations:
animateWithDuration: animations: completion:
animateWithDuration: delay: options: animations: completion:
上面創(chuàng)建動(dòng)畫(huà)塊(animations: )的均是類(lèi)方法宦棺,所以這些動(dòng)畫(huà)塊沒(méi)有綁定任何視圖。因此,可以使用這些方法創(chuàng)建一個(gè)單一的動(dòng)畫(huà)硼补,應(yīng)用于多個(gè)視圖利花。
下面代碼演示了在1秒鐘內(nèi)淡出firstView
微酬、淡入secondView
的操作。
[UIView animateWithDuration:1.0 animations:^{
self.firstView.alpha = 0.0;
self.secondView.alpha = 1.0;
}];
使用上述類(lèi)方法操縱動(dòng)畫(huà)過(guò)程中橄务,firstView
和secondView
兩個(gè)視圖將暫時(shí)禁用用戶交互幔托,即用戶不能與正在運(yùn)行動(dòng)畫(huà)的視圖交互。如果想要實(shí)現(xiàn)更復(fù)雜的功能蜂挪,需要使用CoreAnimation
框架柑司。雖然使用CoreAnimation
框架可以對(duì)動(dòng)畫(huà)進(jìn)行暫停、恢復(fù)锅劝、停止等操作攒驰,但會(huì)產(chǎn)生大量代碼,需要大量工作故爵,可以使用pop一類(lèi)的第三方庫(kù)玻粪。
1. UIViewPropertyAnimator
在iOS 10,Apple在UIKit
中增加了UIViewPropertyAnimator
類(lèi)诬垂,使用該類(lèi)實(shí)現(xiàn)的動(dòng)畫(huà)可以在結(jié)束前進(jìn)行暫停劲室、恢復(fù)、停止等操作结窘。UIViewPropertyAnimator
類(lèi)對(duì)象通過(guò)操作視圖的屬性來(lái)產(chǎn)生所需動(dòng)畫(huà)很洋,但不是所有屬性的改變都會(huì)產(chǎn)生動(dòng)畫(huà),可產(chǎn)生動(dòng)畫(huà)的屬性包括frame
隧枫、center
喉磁、alpha
和transform
。
UIViewPropertyAnimator
類(lèi)遵守了UIViewAnimating
和UIViewImplicitlyAnimating
協(xié)議官脓。UIViewAnimating
協(xié)議中方法用于控制動(dòng)畫(huà)的狀態(tài)协怒,包括開(kāi)始startAnimation
、暫停pauseAnimation
卑笨、結(jié)束stopAnimation:
動(dòng)畫(huà)孕暇,也有一些屬性用于反映當(dāng)前動(dòng)畫(huà)狀態(tài)。動(dòng)畫(huà)運(yùn)行時(shí)赤兴,這些狀態(tài)隨之更新妖滔。UIViewPropertyAnimator
對(duì)象(后面稱(chēng)為animator)在處理動(dòng)畫(huà)期間會(huì)經(jīng)歷UIViewAnimatingStateInactive
、UIViewAnimatingStateActive
桶良、UIViewAnimatingStateStopped
不同狀態(tài)座舍。下圖顯示了animator狀態(tài)變化。
Inactive狀態(tài)是animator的初始狀態(tài)艺普。每一個(gè)新創(chuàng)建的animator均處于inactive狀態(tài)簸州,animator在動(dòng)畫(huà)結(jié)束后返回到inactive狀態(tài)鉴竭。在非活躍狀態(tài)配置的動(dòng)畫(huà),其運(yùn)行持續(xù)時(shí)間為指定的完整持續(xù)時(shí)間岸浑;使用addAnimations:
方法添加的動(dòng)畫(huà)搏存,添加后立即開(kāi)始執(zhí)行,與其它動(dòng)畫(huà)同時(shí)結(jié)束矢洲,即運(yùn)行時(shí)間為剩余持續(xù)時(shí)間璧眠,非完整持續(xù)時(shí)間。
當(dāng)調(diào)用startAnimation
或pauseAnimation
方法后读虏,animator變?yōu)閍ctive狀態(tài)责静。處于active狀態(tài)的animator可能正在運(yùn)行動(dòng)畫(huà),也可能將動(dòng)畫(huà)暫停盖桥,以便修改動(dòng)畫(huà)灾螃。當(dāng)動(dòng)畫(huà)運(yùn)行到指定位置結(jié)束后,animator將返回到inactive狀態(tài)揩徊,以便重新配置動(dòng)畫(huà)腰鬼。
調(diào)用stopAnimation:
方法后,將停止所有正在運(yùn)行的動(dòng)畫(huà)塑荒,并將相應(yīng)視圖屬性的值更新為調(diào)用stopAnimation:
方法時(shí)的值熄赡。當(dāng)stopAnimation:
參數(shù)為YES
時(shí),animator狀態(tài)直接改變?yōu)?code>UIViewAnimatingStateInactive齿税,且不再執(zhí)行任何動(dòng)作彼硫;當(dāng)stopAnimation:
參數(shù)為NO
時(shí),animator狀態(tài)改變?yōu)?code>UIViewAnimatingStateStopped凌箕,隨后拧篮,可以調(diào)用finishAnimationAtPosition:
方法執(zhí)行animator的最終動(dòng)作。例如陌知,執(zhí)行completion塊他托。對(duì)finishAnimationAtPosition:
方法的調(diào)用不是必須的,也可以在調(diào)用finishAnimationAtPosition:
方法前先執(zhí)行其它動(dòng)畫(huà)仆葡。
UIViewImplicitlyAnimating
協(xié)議用于在動(dòng)畫(huà)進(jìn)行過(guò)程中修改動(dòng)畫(huà),如添加動(dòng)畫(huà)addAnimations:
志笼、添加completion塊addCompletion:
等沿盅。
2. 示例1
下面通過(guò)一個(gè)demo來(lái)學(xué)習(xí)UIViewPropertyAnimator
。
創(chuàng)建Single View Application模板的應(yīng)用纫溃,demo名稱(chēng)為PropertyAnimator腰涧。在storyboard中添加一個(gè)UIView
、三個(gè)UIButton
紊浩、兩個(gè)UILabel
窖铡、一個(gè)UISwitch
疗锐、一個(gè)UIStepper
和一個(gè)UISlider
。布局如下:
使用Auto Layout费彼、Stack View對(duì)視圖進(jìn)行自動(dòng)布局滑臊,通過(guò)上圖可以看到所添加的約束,其中Stack View的spacing均為
20
箍铲。如果你對(duì)自動(dòng)布局不熟悉雇卷,可以查看Auto Layout的使用和Auto Layout中Stack View的使用兩篇文章。
從storyboard向ViewController.m
添加IBOutlet屬性颠猴。如下所示:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIButton *restartButton;
@property (weak, nonatomic) IBOutlet UIButton *startStopButton;
@property (weak, nonatomic) IBOutlet UIButton *pauseButton;
@property (weak, nonatomic) IBOutlet UISwitch *reverseAnimationSwitch;
@property (weak, nonatomic) IBOutlet UIStepper *durationStepper;
@property (weak, nonatomic) IBOutlet UILabel *durationLabel;
@end
最后再添加以下三個(gè)屬性关划。
@interface ViewController ()
...
@property (strong, nonatomic) UIViewPropertyAnimator *propertyAnimator;
@property (assign, nonatomic) NSTimeInterval duration;
@property (assign, nonatomic) CGRect startFrame;
@end
現(xiàn)在添加一個(gè)setupAnimator
的方法,用于配制動(dòng)畫(huà)翘瓮。
- (void)setupAnimator {
// 1.動(dòng)畫(huà)初始位置贮折。
self.redView.frame = self.startFrame;
// 2.動(dòng)畫(huà)終點(diǎn)位置。
CGFloat margin = 16.0;
CGFloat screenWidth = CGRectGetWidth(self.view.frame);
CGFloat finalX = screenWidth - CGRectGetWidth(self.redView.frame) - margin;
CGRect finalRect = CGRectMake(finalX, self.redView.frame.origin.y, self.redView.frame.size.width, self.redView.frame.size.height);
// 3.初始化動(dòng)畫(huà)资盅。
self.propertyAnimator = [[UIViewPropertyAnimator alloc] initWithDuration:self.duration
curve:UIViewAnimationCurveEaseIn
animations:^{
self.redView.frame = finalRect;
}];
// 4.為動(dòng)畫(huà)添加完成塊调榄。
ViewController * __weak weakSelf = self;
ViewController *vc = weakSelf;
if (vc) {
[self.propertyAnimator addCompletion:^(UIViewAnimatingPosition finalPosition) {
[vc.startStopButton setTitle:@"Start" forState:UIControlStateNormal];
vc.startStopButton.enabled = NO;
vc.pauseButton.enabled = NO;
vc.restartButton.enabled = YES;
}];
}
vc = nil;
}
在上面的代碼中,注釋3部分用于初始化動(dòng)畫(huà)律姨,其中initWithDuration:
的參數(shù)為動(dòng)畫(huà)持續(xù)時(shí)間振峻;curve:
參數(shù)用來(lái)設(shè)定動(dòng)畫(huà)曲線。這里有以下四種可選曲線:
- UIViewAnimationCurveEaseInOut:這種曲線的動(dòng)畫(huà)開(kāi)始緩慢择份,在其持續(xù)時(shí)間的中間加速扣孟,然后在完成之前再次減慢。這是大多數(shù)動(dòng)畫(huà)的默認(rèn)曲線荣赶。
- UIViewAnimationCurveEaseIn:動(dòng)畫(huà)開(kāi)始時(shí)緩慢凤价,然后加速,直到動(dòng)畫(huà)結(jié)束拔创。這里選用這種類(lèi)型動(dòng)畫(huà)曲線利诺。
- UIViewAnimationCurveEaseOut:動(dòng)畫(huà)開(kāi)始時(shí)速度很快,在結(jié)束前開(kāi)始減速剩燥。
- UIViewAnimationCurveLinear:在動(dòng)畫(huà)持續(xù)時(shí)間內(nèi)慢逾,動(dòng)畫(huà)勻速運(yùn)行。
最后在動(dòng)畫(huà)塊內(nèi)配置動(dòng)畫(huà)灭红。注釋4部分侣滩,為動(dòng)畫(huà)塊添加完成回調(diào)函數(shù)。這里需要注意避免形成循環(huán)引用变擒,使用__weak
聲明的weakSelf
替代self
君珠,因?yàn)閴K內(nèi)多次用到weakSelf
,可能在第一次調(diào)用weakSelf
時(shí)weakSelf
存在娇斑,但后面再次調(diào)用weakSelf
時(shí)策添,weakSelf
已被釋放材部,所以這里再次將其轉(zhuǎn)換為強(qiáng)引用類(lèi)型vc
,不再需要vc
時(shí)唯竹,需要手動(dòng)釋放乐导。
想要了解更多關(guān)于塊的用法,查看Block的用法一文摩窃。
從storyboard中選中UIStepper
控件兽叮,拖拽到代碼中,以添加響應(yīng)事件猾愿。
- (IBAction)stepperValueChanged:(UIStepper *)sender {
// 1.設(shè)置動(dòng)畫(huà)持續(xù)時(shí)間為UIStpper的值鹦聪。
self.duration = sender.value;
// 2.同步更新到label。
self.durationLabel.text = [NSString stringWithFormat:@"%.1f",sender.value];
}
上述代碼用于設(shè)定動(dòng)畫(huà)持續(xù)時(shí)間蒂秘。
在storyboard中選中Start按鈕泽本,拖拽到ViewController.m
實(shí)現(xiàn)部分,以添加響應(yīng)事件姻僧,響應(yīng)事件方法名稱(chēng)為startStopPause
规丽。在storyboard中選中Pause按鈕,也拖拽到startStopPause:
響應(yīng)事件撇贺,以便在點(diǎn)擊Start或Pause任一按鈕時(shí)赌莺,均調(diào)用startStopPause:
方法。
- (IBAction)startStopPause:(UIButton *)sender {
// 1.禁用restartButton松嘶,propertyAnimator不存在時(shí)艘狭,配置propertyAnimator。
self.restartButton.enabled = NO;
if (!self.propertyAnimator) {
[self setupAnimator];
}
if (sender == self.pauseButton) {
// 2.點(diǎn)擊Pause按鈕時(shí)翠订,根據(jù)當(dāng)前動(dòng)畫(huà)狀態(tài)更新視圖巢音。
self.propertyAnimator.isRunning ? [self.propertyAnimator pauseAnimation] : [self.propertyAnimator startAnimation];
NSString *title = self.propertyAnimator.isRunning ? @"Pause" : @"Unpause";
[self.pauseButton setTitle:title forState:UIControlStateNormal];
self.startStopButton.enabled = self.propertyAnimator.isRunning;
}
else
{
// 3.點(diǎn)擊Start按鈕時(shí),根據(jù)當(dāng)前動(dòng)畫(huà)狀態(tài)更新視圖尽超。
switch (self.propertyAnimator.state) {
case UIViewAnimatingStateInactive:
[self.propertyAnimator startAnimation];
[self.startStopButton setTitle:@"Stop" forState:UIControlStateNormal];
self.pauseButton.enabled = YES;
NSLog(@"UIViewAnimatingStateInactive");
break;
case UIViewAnimatingStateActive:
if (self.propertyAnimator.isRunning) {
[self.propertyAnimator stopAnimation:NO];
[self.propertyAnimator finishAnimationAtPosition:UIViewAnimatingPositionCurrent];
[self.startStopButton setTitle:@"Start" forState:UIControlStateNormal];
self.pauseButton.enabled = NO;
}
else
{
[self.propertyAnimator startAnimation];
[self.startStopButton setTitle:@"Stop" forState:UIControlStateNormal];
self.pauseButton.enabled = YES;
}
NSLog(@"UIViewAnimatingStateActive");
break;
case UIViewAnimatingStateStopped:
NSLog(@"UIViewAnimatingStateStopped");
break;
default:
break;
}
}
}
上面代碼根據(jù)所點(diǎn)擊的按鈕官撼,進(jìn)行不同的響應(yīng)操作。當(dāng)點(diǎn)擊的是Start按鈕時(shí)似谁,根據(jù)propertyAnimator
所處的狀態(tài)執(zhí)行不同操作傲绣。
從storyboard中拖拽UISwitch
控件到代碼中,以創(chuàng)建響應(yīng)事件巩踏。
- (IBAction)reverseAnimationSwitchValueChanged:(UISwitch *)sender {
if (self.propertyAnimator && self.propertyAnimator.isRunning) {
// 在propertyAnimator存在斜筐,且正在運(yùn)行時(shí),根據(jù)UISwitch的值調(diào)整propertyAnimator的方向蛀缝。
self.propertyAnimator.reversed = sender.isOn;
}
}
從storyboard中拖拽Restart Animation按鈕到代碼中,以創(chuàng)建響應(yīng)事件目代。
- (IBAction)restartAnimation:(UIButton *)sender {
// 點(diǎn)擊RestartAnimation按鈕時(shí)屈梁,重新配置動(dòng)畫(huà)嗤练,啟用Start按鈕,將reverseAnimationSwitch設(shè)置為關(guān)閉狀態(tài)在讶。
[self setupAnimator];
self.startStopButton.enabled = YES;
self.reverseAnimationSwitch.on = NO;
}
可以通過(guò)為fractionComplete
屬性賦值煞抬,設(shè)置動(dòng)畫(huà)進(jìn)度百分比。從storyboard中拖拽UISlider
控件到代碼中构哺,創(chuàng)建響應(yīng)事件革答。
- (IBAction)scrubAnimation:(UISlider *)sender {
if (!self.propertyAnimator) {
[self setupAnimator];
}
// 1.當(dāng)propertyAnimator正在運(yùn)行時(shí),暫停該動(dòng)畫(huà)曙强,否則在停止拖動(dòng)UISlider后残拐,動(dòng)畫(huà)會(huì)繼續(xù)運(yùn)行。
if (self.propertyAnimator.isRunning) {
[self.propertyAnimator pauseAnimation];
}
// 2.設(shè)置動(dòng)畫(huà)百分比碟嘴。
self.propertyAnimator.fractionComplete = sender.value;
}
最后溪食,記得設(shè)置startFrame
位置、pauseButton
初始狀態(tài)娜扇。
- (void)viewDidLoad {
[super viewDidLoad];
// 設(shè)置startFrame位置错沃,pauseButton狀態(tài)。
self.startFrame = CGRectMake(16, 45, 100, 100);
self.pauseButton.enabled = NO;
}
現(xiàn)在運(yùn)行demo雀瓢,效果如下枢析。
3. 示例2
UIViewPropertyAnimator
除了可以使用原有的UIViewAnimationCurve
時(shí)間曲線函數(shù),還新增了UISpringTimingParameters
刃麸、UICubicTimingParameters
兩個(gè)時(shí)間曲線函數(shù)醒叁。
添加Cocoa Touch Class模版的文件,其父類(lèi)為UIViewController
嫌蚤,名稱(chēng)為TimingCurvesViewController
辐益。在storyboard中添加UIViewController
,并設(shè)置其父類(lèi)為TimingCurvesViewController
脱吱。
在剛添加的視圖控制器上添加四個(gè)UIView
智政、四個(gè)UILabel
。同時(shí)選中兩個(gè)視圖控制器箱蝠,添加UITabBarController
续捂,如下所示:
為TimingCurvesViewController
上的UIView
創(chuàng)建IBOutlet連接,并添加以下幾個(gè)屬性宦搬。
#import "TimingCurvesViewController.h"
@interface TimingCurvesViewController ()
@property (weak, nonatomic) IBOutlet UIView *redView;
@property (weak, nonatomic) IBOutlet UIView *blueView;
@property (weak, nonatomic) IBOutlet UIView *greenView;
@property (weak, nonatomic) IBOutlet UIView *yellowView;
@property (assign, nonatomic) CGRect redStartFrame;
@property (assign, nonatomic) CGRect blueStartFrame;
@property (assign, nonatomic) CGRect greenStartFrame;
@property (assign, nonatomic) CGRect yellowStartFrame;
@property (strong, nonatomic) UIViewPropertyAnimator *redAnimator;
@property (strong, nonatomic) UIViewPropertyAnimator *blueAnimator;
@property (strong, nonatomic) UIViewPropertyAnimator *greenAnimator;
@property (strong, nonatomic) UIViewPropertyAnimator *yellowStartAnimator;
@property (strong, nonatomic) NSTimer *timer;
@property (assign, nonatomic) NSTimeInterval durationOfAnimation;
@end
在TimingCurvesViewController.m
的viewDidLoad
方法中牙瓢,設(shè)置四個(gè)UIView
的初始位置和durationOfAnimation
值。
- (void)viewDidLoad {
[super viewDidLoad];
// 1.設(shè)置UIView初始位置间校。
self.redStartFrame = CGRectMake(16, 50, squareSize, squareSize);
self.blueStartFrame = CGRectMake(16, 150, squareSize, squareSize);
self.greenStartFrame = CGRectMake(16, 250, squareSize, squareSize);
self.yellowStartFrame = CGRectMake(16, 350, squareSize, squareSize);
// 2.為durationOfAnimation賦初始值2.0矾克。
self.durationOfAnimation = 2.0;
}
3.1 UIViewAnimationCurve
UIViewAnimationCurve時(shí)間曲線函數(shù)分為UIViewAnimationCurveEaseInOut
、UIViewAnimationCurveEaseIn
憔足、UIViewAnimationCurveEaseOut
和UIViewAnimationCurveLinear
四種胁附。
在TimingCurvesViewController.m
實(shí)現(xiàn)部分添加以下代碼來(lái)使用上述四種時(shí)間曲線酒繁。
// Default Curves
- (void)startAnimationsWithDefaultCurves {
// 1.四個(gè)視圖使用不同類(lèi)型時(shí)間曲線函數(shù)。
self.redAnimator = [self animatorForView:self.redView startFrame:self.redStartFrame curve:UIViewAnimationCurveLinear];
self.blueAnimator = [self animatorForView:self.blueView startFrame:self.blueStartFrame curve:UIViewAnimationCurveEaseIn];
self.greenAnimator = [self animatorForView:self.greenView startFrame:self.greenStartFrame curve:UIViewAnimationCurveEaseOut];
self.yellowAnimator = [self animatorForView:self.yellowView startFrame:self.yellowStartFrame curve:UIViewAnimationCurveEaseInOut];
}
- (UIViewPropertyAnimator *)animatorForView:(UIView *)view startFrame:(CGRect)startFrame curve:(UIViewAnimationCurve)curve {
// 2.視圖初始位置控妻,動(dòng)畫(huà)結(jié)束時(shí)視圖位置州袒。
view.frame = startFrame;
CGRect finalRect = [self finalRectWithStartFrame:startFrame];
// 3.配置動(dòng)畫(huà)。
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:self.durationOfAnimation curve:curve animations:^{
view.frame = finalRect;
}];
return animator;
}
#pragma mark Help Methods
- (CGRect)finalRectWithStartFrame:(CGRect)startFrame {
// 4.計(jì)算出動(dòng)畫(huà)結(jié)束時(shí)位置弓候。
CGFloat margin = 16;
CGFloat screenWidth = CGRectGetWidth(self.view.frame);
CGFloat finalX = screenWidth - margin - squareSize;
CGRect finalRect = CGRectMake(finalX, startFrame.origin.y, squareSize, squareSize);
return finalRect;
}
上述代碼非常簡(jiǎn)單郎哭,在注釋1部分使用UIViewAnimationCurveLinear
、UIViewAnimationCurveEaseIn
菇存、UIViewAnimationCurveEaseOut
和UIViewAnimationCurveEaseInOut
四種時(shí)間曲線夸研。注釋4的方法后面會(huì)多次用到。
在TimingCurvesViewController.m
實(shí)現(xiàn)部分添加viewDidAppear:
方法撰筷,用定時(shí)器觸發(fā)動(dòng)畫(huà)陈惰。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// 1.在1.5倍durationOfAnimation時(shí)間后,觸發(fā)動(dòng)畫(huà)毕籽。
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.durationOfAnimation*1.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
// 2.動(dòng)畫(huà)使用默認(rèn)時(shí)間曲線函數(shù)抬闯。
[self startAnimationsWithDefaultCurves];
// 啟動(dòng)動(dòng)畫(huà)。
[self.redAnimator startAnimation];
[self.blueAnimator startAnimation];
[self.greenAnimator startAnimation];
[self.yellowAnimator startAnimation];
}];
}
如果使用標(biāo)準(zhǔn)方法(initWith方法)創(chuàng)建動(dòng)畫(huà)关筒,必須通過(guò)調(diào)用startAnimation
方法開(kāi)始動(dòng)畫(huà)溶握;如果想要?jiǎng)?chuàng)建動(dòng)畫(huà)后立即開(kāi)始執(zhí)行動(dòng)畫(huà),請(qǐng)使用runningPropertyAnimatorWithDuration: delay: options: animations: completion:
方法蒸播。
運(yùn)行demo睡榆,如下所示:
通過(guò)上面代碼可以看到:
- UIViewAnimationCurveEaseInOut:這種曲線的動(dòng)畫(huà)開(kāi)始緩慢,在其持續(xù)時(shí)間的中間加速袍榆,然后在完成之前再次減慢胀屿。這是大多數(shù)動(dòng)畫(huà)的默認(rèn)曲線。
- UIViewAnimationCurveEaseIn:動(dòng)畫(huà)開(kāi)始時(shí)緩慢包雀,然后加速宿崭,直到動(dòng)畫(huà)結(jié)束。
- UIViewAnimationCurveEaseOut:動(dòng)畫(huà)開(kāi)始時(shí)速度很快才写,在結(jié)束前開(kāi)始減速葡兑。
- UIViewAnimationCurveLinear:在動(dòng)畫(huà)持續(xù)時(shí)間內(nèi),動(dòng)畫(huà)勻速運(yùn)行赞草。
3.2 UICubicTimingParameters
UICubicTimingParameters
允許通過(guò)多個(gè)控制點(diǎn)來(lái)定義三階貝塞爾曲線讹堤,該貝塞爾時(shí)間曲線起點(diǎn)為(0,0),終點(diǎn)為(1,1)厨疙,曲線形狀由兩個(gè)控制點(diǎn)決定洲守。每個(gè)時(shí)間點(diǎn)線的斜率定義了此時(shí)動(dòng)畫(huà)速度。曲線越陡峭,動(dòng)畫(huà)運(yùn)行速度越快岖沛;曲線越平緩暑始,動(dòng)畫(huà)運(yùn)行速度越慢。
下圖的時(shí)間曲線表示動(dòng)畫(huà)在開(kāi)始和結(jié)束時(shí)速度很快婴削,中間運(yùn)行較慢。
控制點(diǎn)范圍為0.0至1.0牙肝。
UICubicTimingParameters
遵守UITimingCurveProvider
協(xié)議唉俗,為遵守UIViewAnimating
協(xié)議的對(duì)象提供時(shí)間曲線(timing curves),如UIViewPropertyAnimator
配椭。
繼續(xù)更新TimingCurvesViewController.m
內(nèi)代碼虫溜,使用UICubicTimingParameters
作為動(dòng)畫(huà)時(shí)間參數(shù)。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// 1.在1.5倍durationOfAnimation時(shí)間后股缸,觸發(fā)動(dòng)畫(huà)衡楞。
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.durationOfAnimation*1.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
// 2.動(dòng)畫(huà)使用默認(rèn)時(shí)間曲線函數(shù)。
// [self startAnimationsWithDefaultCurves];
// 3.使用UICubicTimingParameters
[self startAnimationWithCubicCurves];
// 啟動(dòng)動(dòng)畫(huà)敦姻。
[self.redAnimator startAnimation];
[self.blueAnimator startAnimation];
[self.greenAnimator startAnimation];
[self.yellowAnimator startAnimation];
}];
}
// UICubicTimingParameters
- (void)startAnimationWithCubicCurves {
// 1.中間慢瘾境,開(kāi)始、結(jié)尾快镰惦。
UICubicTimingParameters *redCubicTimingParameters = [[UICubicTimingParameters alloc] initWithControlPoint1:CGPointMake(0.45, 1.0) controlPoint2:CGPointMake(0.55, 0)];
// 2.中間快迷守,開(kāi)始、結(jié)尾慢旺入。
UICubicTimingParameters *blueCubicTimingParameters = [[UICubicTimingParameters alloc] initWithControlPoint1:CGPointMake(1.0, 0.45) controlPoint2:CGPointMake(0, 0.55)];
self.redAnimator = [self animatorForView:self.redView startFrame:self.redStartFrame timingParameters:redCubicTimingParameters];
self.blueAnimator = [self animatorForView:self.blueView startFrame:self.blueStartFrame timingParameters:blueCubicTimingParameters];
}
- (UIViewPropertyAnimator *)animatorForView:(UIView *)view startFrame:(CGRect)startFrame timingParameters:(UICubicTimingParameters *)cubicTimingParameters {
view.frame = startFrame;
CGRect finalRect = [self finalRectWithStartFrame:startFrame];
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:self.durationOfAnimation timingParameters:cubicTimingParameters];
[animator addAnimations:^{
view.frame = finalRect;
}];
return animator;
}
其中兑凿,startAnimationWithCubicCurves
方法內(nèi),注釋1中的控制點(diǎn)決定動(dòng)畫(huà)曲線茵瘾,動(dòng)畫(huà)在中間慢礼华,開(kāi)始和結(jié)尾處快。注釋2相反拗秘。這里只使用了redView
和blueView
兩個(gè)視圖圣絮。
運(yùn)行如下:
3.3 UISpringTimingParameters
由UISpringTimingParameters
提供的時(shí)間曲線會(huì)讓動(dòng)畫(huà)行為與彈簧相似。視圖會(huì)加速向目標(biāo)點(diǎn)運(yùn)動(dòng)聘殖,然后圍繞該目標(biāo)點(diǎn)震蕩晨雳,直到停止。
UISpringTimingParameters
遵守UITimingCurveProvider
協(xié)議奸腺,為遵守UIViewAnimating
協(xié)議的對(duì)象提供時(shí)間曲線餐禁,如UIViewPropertyAnimator
。UISpringTimingParameters
一般用于移動(dòng)屏幕上的視圖突照,也可用于視圖的其它屬性帮非,以獲取類(lèi)似的動(dòng)畫(huà)效果。
繼續(xù)更新TimingCurvesViewController.m
內(nèi)代碼,使用UISpringTimingParameters
作為動(dòng)畫(huà)運(yùn)行時(shí)間參數(shù)末盔。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// 1.在1.5倍durationOfAnimation時(shí)間后筑舅,觸發(fā)動(dòng)畫(huà)。
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.durationOfAnimation*1.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
// 2.動(dòng)畫(huà)使用默認(rèn)時(shí)間曲線函數(shù)陨舱。
// [self startAnimationsWithDefaultCurves];
// 3.使用UICubicTimingParameters翠拣。
// [self startAnimationWithCubicCurves];
// 4.使用UISpringTimingParameters。
[self startAnimationWithSpringCurves];
// 啟動(dòng)動(dòng)畫(huà)游盲。
[self.redAnimator startAnimation];
[self.blueAnimator startAnimation];
[self.greenAnimator startAnimation];
[self.yellowAnimator startAnimation];
}];
}
// UISpringTimingParameters
- (void)startAnimationWithSpringCurves {
// dampingRatio值分別為0.2 1.0 2.0误墓。
CGFloat underDamped = 0.2;
CGFloat criticalDamped = 1.0;
CGFloat overDamped = 2.0;
self.redAnimator = [self animatorForView:self.redView startFrame:self.redStartFrame dampingRatio:underDamped];
self.blueAnimator = [self animatorForView:self.blueView startFrame:self.blueStartFrame dampingRatio:criticalDamped];
self.greenAnimator = [self animatorForView:self.greenView startFrame: self.greenStartFrame dampingRatio:overDamped];
}
- (UIViewPropertyAnimator *)animatorForView:(UIView *)view startFrame:(CGRect)startFrame dampingRatio:(CGFloat)dampingRatio {
view.frame = startFrame;
CGRect finalRect = [self finalRectWithStartFrame:startFrame];
UIViewPropertyAnimator *animator = [[UIViewPropertyAnimator alloc] initWithDuration:self.durationOfAnimation dampingRatio:dampingRatio animations:^{
view.frame = finalRect;
}];
return animator;
}
另外,也可以使用initWithMass: stiffness: damping: initialVelocity:
方法益缎,該方法會(huì)把阻尼系數(shù)(damping)谜慌、質(zhì)量參數(shù)(mass)、剛性系數(shù)(stiffness)和初始速度(initial velocity)帶入給定公式莺奔,以獲取更為真實(shí)的效果欣范。
運(yùn)行demo,如下所示:
UIDynamicAnimator
中的UISnapBehavior
也可以產(chǎn)生彈簧(spring)效果令哟,UISnapBehavior
是移動(dòng)到指定點(diǎn)point恼琼,如下圖所示。想要全面了解UIKitDynamicAnimator
励饵,可以查看一篇文章學(xué)會(huì)使用UIKit Dynamics驳癌。
Demo名稱(chēng):PropertyAnimator
源碼地址:https://github.com/pro648/BasicDemos-iOS
參考資料: