iOS的動(dòng)畫(huà)效果一直都很棒很,給人的感覺(jué)就是很炫酷很流暢,起到增強(qiáng)用戶(hù)體驗(yàn)的作用。在APP開(kāi)發(fā)中實(shí)現(xiàn)動(dòng)畫(huà)效果有很多種方式,對(duì)于簡(jiǎn)單的應(yīng)用場(chǎng)景,我們可以使用UIKit提供的動(dòng)畫(huà)來(lái)實(shí)現(xiàn)。
UIView動(dòng)畫(huà)實(shí)質(zhì)上是對(duì)Core Animation的封裝,提供簡(jiǎn)潔的動(dòng)畫(huà)接口。
UIView動(dòng)畫(huà)可以設(shè)置的動(dòng)畫(huà)屬性有:
1、大小變化(frame)
2、拉伸變化(bounds)
3、中心位置(center)
4、旋轉(zhuǎn)(transform)
5、透明度(alpha)
6、背景顏色(backgroundColor)
7、拉伸內(nèi)容(contentStretch)
1)動(dòng)畫(huà)的開(kāi)始和結(jié)束方法
1.1 動(dòng)畫(huà)開(kāi)始標(biāo)記
[UIViewbeginAnimations:(nullableNSString *)context:(nullablevoid *)];
第一個(gè)參數(shù):動(dòng)畫(huà)標(biāo)識(shí)
第二個(gè)參數(shù):附加參數(shù),在設(shè)置了代理的情況下,此參數(shù)將發(fā)送到setAnimationWillStartSelector和setAnimationDidStopSelector所指定的方法。大部分情況下,我們?cè)O(shè)置為nil即可。
1.2 結(jié)束動(dòng)畫(huà)標(biāo)記
[UIViewcommitAnimations];
2)動(dòng)畫(huà)參數(shù)的設(shè)置方法
//動(dòng)畫(huà)持續(xù)時(shí)間[UIViewsetAnimationDuration:(NSTimeInterval)];
//動(dòng)畫(huà)的代理對(duì)象[UIViewsetAnimationDelegate:(nullableid)];
//設(shè)置動(dòng)畫(huà)將開(kāi)始時(shí)代理對(duì)象執(zhí)行的SEL[UIViewsetAnimationWillStartSelector:(nullable SEL)];
//設(shè)置動(dòng)畫(huà)結(jié)束時(shí)代理對(duì)象執(zhí)行的SEL[UIViewsetAnimationDidStopSelector:(nullable SEL)];
//設(shè)置動(dòng)畫(huà)延遲執(zhí)行的時(shí)間[UIViewsetAnimationDelay:(NSTimeInterval)];
//設(shè)置動(dòng)畫(huà)的重復(fù)次數(shù)[UIViewsetAnimationRepeatCount:(float)];
//設(shè)置動(dòng)畫(huà)的曲線(xiàn)[UIViewsetAnimationCurve:(UIViewAnimationCurve)];UIViewAnimationCurve的枚舉值如下:UIViewAnimationCurveEaseInOut,// 慢進(jìn)慢出(默認(rèn)值)UIViewAnimationCurveEaseIn,// 慢進(jìn)UIViewAnimationCurveEaseOut,// 慢出UIViewAnimationCurveLinear// 勻速
//設(shè)置是否從當(dāng)前狀態(tài)開(kāi)始播放動(dòng)畫(huà)[UIViewsetAnimationBeginsFromCurrentState:YES];? ? 假設(shè)上一個(gè)動(dòng)畫(huà)正在播放,且尚未播放完畢,我們將要進(jìn)行一個(gè)新的動(dòng)畫(huà):? ? 當(dāng)為YES時(shí):動(dòng)畫(huà)將從上一個(gè)動(dòng)畫(huà)所在的狀態(tài)開(kāi)始播放? ? 當(dāng)為NO時(shí):動(dòng)畫(huà)將從上一個(gè)動(dòng)畫(huà)所指定的最終狀態(tài)開(kāi)始播放(此時(shí)上一個(gè)動(dòng)畫(huà)馬上結(jié)束)
//設(shè)置動(dòng)畫(huà)是否繼續(xù)執(zhí)行相反的動(dòng)畫(huà)[UIViewsetAnimationRepeatAutoreverses:(BOOL)];
//是否禁用動(dòng)畫(huà)效果(對(duì)象屬性依然會(huì)被改變,只是沒(méi)有動(dòng)畫(huà)效果)[UIViewsetAnimationsEnabled:(BOOL)];
//設(shè)置視圖的過(guò)渡效果[UIViewsetAnimationTransition:(UIViewAnimationTransition) forView:(nonnullUIView*) cache:(BOOL)];? ? 第一個(gè)參數(shù):UIViewAnimationTransition的枚舉值如下UIViewAnimationTransitionNone,//不使用動(dòng)畫(huà)UIViewAnimationTransitionFlipFromLeft,//從左向右旋轉(zhuǎn)翻頁(yè)UIViewAnimationTransitionFlipFromRight,//從右向左旋轉(zhuǎn)翻頁(yè)UIViewAnimationTransitionCurlUp,//從下往上卷曲翻頁(yè)UIViewAnimationTransitionCurlDown,//從上往下卷曲翻頁(yè)第二個(gè)參數(shù):需要過(guò)渡效果的View? ? 第三個(gè)參數(shù):是否使用視圖緩存,YES:視圖在開(kāi)始和結(jié)束時(shí)渲染一次;NO:視圖在每一幀都渲染
1、屬性變化動(dòng)畫(huà)(以frame變化為例)
- (void)changeFrame {? ? [UIViewbeginAnimations:@"FrameAni"context:nil];? ? [UIViewsetAnimationDuration:1.0];? ? [UIViewsetAnimationDelegate:self];? ? [UIViewsetAnimationWillStartSelector:@selector(startAni:)];? ? [UIViewsetAnimationDidStopSelector:@selector(stopAni:)];? ? [UIViewsetAnimationRepeatCount:1];? ? [UIViewsetAnimationCurve:UIViewAnimationCurveEaseInOut];self.cartCenter.frame=self.centerShow.frame;? ? [UIViewcommitAnimations];}- (void)startAni:(NSString*)aniID {NSLog(@"%@ start",aniID);}- (void)stopAni:(NSString*)aniID {NSLog(@"%@ stop",aniID);}
動(dòng)畫(huà)效果:

NormalAni.gif
2、轉(zhuǎn)場(chǎng)效果動(dòng)畫(huà)(以Flip效果為例)
- (void)flipAni {? ? [UIViewbeginAnimations:@"FlipAni"context:nil];? ? [UIViewsetAnimationDuration:1.0];? ? [UIViewsetAnimationDelegate:self];? ? [UIViewsetAnimationWillStartSelector:@selector(startAni:)];? ? [UIViewsetAnimationDidStopSelector:@selector(stopAni:)];? ? [UIViewsetAnimationRepeatCount:1];? ? [UIViewsetAnimationCurve:UIViewAnimationCurveEaseInOut];? ? [UIViewsetAnimationTransition:UIViewAnimationTransitionFlipFromLeftforView:self.centerShowcache:YES];self.centerShow.image= [UIImageimageNamed:@"service"];? ? [UIViewcommitAnimations];}
動(dòng)畫(huà)效果:

ScreenTransitionAni.gif
iOS4.0以后,增加了Block動(dòng)畫(huà)塊,提供更簡(jiǎn)潔的方式來(lái)實(shí)現(xiàn)動(dòng)畫(huà)。
1、最簡(jiǎn)潔的Block動(dòng)畫(huà):包含時(shí)間和動(dòng)畫(huà)
[UIViewanimateWithDuration:(NSTimeInterval)//動(dòng)畫(huà)持續(xù)時(shí)間animations:^{//執(zhí)行的動(dòng)畫(huà)}];
2、帶有動(dòng)畫(huà)完成回調(diào)的Block動(dòng)畫(huà)
[UIViewanimateWithDuration:(NSTimeInterval)//動(dòng)畫(huà)持續(xù)時(shí)間animations:^{//執(zhí)行的動(dòng)畫(huà)}? ? ? ? ? ? ? ? completion:^(BOOLfinished) {//動(dòng)畫(huà)執(zhí)行完畢后的操作}];
3、可設(shè)置延遲時(shí)間和過(guò)渡效果的Block動(dòng)畫(huà)
[UIViewanimateWithDuration:(NSTimeInterval)//動(dòng)畫(huà)持續(xù)時(shí)間delay:(NSTimeInterval)//動(dòng)畫(huà)延遲執(zhí)行的時(shí)間options:(UIViewAnimationOptions)//動(dòng)畫(huà)的過(guò)渡效果animations:^{//執(zhí)行的動(dòng)畫(huà)}? ? ? ? ? ? ? ? completion:^(BOOLfinished) {//動(dòng)畫(huà)執(zhí)行完畢后的操作}];
UIViewAnimationOptions的枚舉值如下,可組合使用:
UIViewAnimationOptionLayoutSubviews//進(jìn)行動(dòng)畫(huà)時(shí)布局子控件UIViewAnimationOptionAllowUserInteraction//進(jìn)行動(dòng)畫(huà)時(shí)允許用戶(hù)交互UIViewAnimationOptionBeginFromCurrentState//從當(dāng)前狀態(tài)開(kāi)始動(dòng)畫(huà)UIViewAnimationOptionRepeat//無(wú)限重復(fù)執(zhí)行動(dòng)畫(huà)UIViewAnimationOptionAutoreverse//執(zhí)行動(dòng)畫(huà)回路UIViewAnimationOptionOverrideInheritedDuration//忽略嵌套動(dòng)畫(huà)的執(zhí)行時(shí)間設(shè)置UIViewAnimationOptionOverrideInheritedCurve//忽略嵌套動(dòng)畫(huà)的曲線(xiàn)設(shè)置UIViewAnimationOptionAllowAnimatedContent//轉(zhuǎn)場(chǎng):進(jìn)行動(dòng)畫(huà)時(shí)重繪視圖UIViewAnimationOptionShowHideTransitionViews//轉(zhuǎn)場(chǎng):移除(添加和移除圖層的)動(dòng)畫(huà)效果UIViewAnimationOptionOverrideInheritedOptions//不繼承父動(dòng)畫(huà)設(shè)置UIViewAnimationOptionCurveEaseInOut//時(shí)間曲線(xiàn),慢進(jìn)慢出(默認(rèn)值)UIViewAnimationOptionCurveEaseIn//時(shí)間曲線(xiàn),慢進(jìn)UIViewAnimationOptionCurveEaseOut//時(shí)間曲線(xiàn),慢出UIViewAnimationOptionCurveLinear//時(shí)間曲線(xiàn),勻速UIViewAnimationOptionTransitionNone//轉(zhuǎn)場(chǎng),不使用動(dòng)畫(huà)UIViewAnimationOptionTransitionFlipFromLeft//轉(zhuǎn)場(chǎng),從左向右旋轉(zhuǎn)翻頁(yè)UIViewAnimationOptionTransitionFlipFromRight//轉(zhuǎn)場(chǎng),從右向左旋轉(zhuǎn)翻頁(yè)UIViewAnimationOptionTransitionCurlUp//轉(zhuǎn)場(chǎng),下往上卷曲翻頁(yè)UIViewAnimationOptionTransitionCurlDown//轉(zhuǎn)場(chǎng),從上往下卷曲翻頁(yè)UIViewAnimationOptionTransitionCrossDissolve//轉(zhuǎn)場(chǎng),交叉消失和出現(xiàn)UIViewAnimationOptionTransitionFlipFromTop//轉(zhuǎn)場(chǎng),從上向下旋轉(zhuǎn)翻頁(yè)UIViewAnimationOptionTransitionFlipFromBottom//轉(zhuǎn)場(chǎng),從下向上旋轉(zhuǎn)翻頁(yè)
4、spring動(dòng)畫(huà)
iOS7.0后新增Spring動(dòng)畫(huà)(ios系統(tǒng)動(dòng)畫(huà)大部分采用Spring Animation,適用于所有可被添加動(dòng)畫(huà)效果的屬性)
[UIViewanimateWithDuration:(NSTimeInterval)//動(dòng)畫(huà)持續(xù)時(shí)間delay:(NSTimeInterval)//動(dòng)畫(huà)延遲執(zhí)行的時(shí)間usingSpringWithDamping:(CGFloat)//震動(dòng)效果,范圍0~1,數(shù)值越小震動(dòng)效果越明顯initialSpringVelocity:(CGFloat)//初始速度,數(shù)值越大初始速度越快options:(UIViewAnimationOptions)//動(dòng)畫(huà)的過(guò)渡效果animations:^{//執(zhí)行的動(dòng)畫(huà)}? ? ? ? ? ? ? ? ? completion:^(BOOLfinished) {//動(dòng)畫(huà)執(zhí)行完畢后的操作}];
5、Keyframes動(dòng)畫(huà)
iOS7.0后新增關(guān)鍵幀動(dòng)畫(huà),支持屬性關(guān)鍵幀,不支持路徑關(guān)鍵幀
[UIViewanimateKeyframesWithDuration:(NSTimeInterval)//動(dòng)畫(huà)持續(xù)時(shí)間delay:(NSTimeInterval)//動(dòng)畫(huà)延遲執(zhí)行的時(shí)間options:(UIViewKeyframeAnimationOptions)//動(dòng)畫(huà)的過(guò)渡效果animations:^{//執(zhí)行的關(guān)鍵幀動(dòng)畫(huà)}? ? ? ? ? ? ? ? ? ? ? ? ? completion:^(BOOLfinished) {//動(dòng)畫(huà)執(zhí)行完畢后的操作}];
UIViewKeyframeAnimationOptions的枚舉值如下,可組合使用:
UIViewAnimationOptionLayoutSubviews//進(jìn)行動(dòng)畫(huà)時(shí)布局子控件UIViewAnimationOptionAllowUserInteraction//進(jìn)行動(dòng)畫(huà)時(shí)允許用戶(hù)交互UIViewAnimationOptionBeginFromCurrentState//從當(dāng)前狀態(tài)開(kāi)始動(dòng)畫(huà)UIViewAnimationOptionRepeat//無(wú)限重復(fù)執(zhí)行動(dòng)畫(huà)UIViewAnimationOptionAutoreverse//執(zhí)行動(dòng)畫(huà)回路UIViewAnimationOptionOverrideInheritedDuration//忽略嵌套動(dòng)畫(huà)的執(zhí)行時(shí)間設(shè)置UIViewAnimationOptionOverrideInheritedOptions//不繼承父動(dòng)畫(huà)設(shè)置UIViewKeyframeAnimationOptionCalculationModeLinear//運(yùn)算模式 :連續(xù)UIViewKeyframeAnimationOptionCalculationModeDiscrete//運(yùn)算模式 :離散UIViewKeyframeAnimationOptionCalculationModePaced//運(yùn)算模式 :均勻執(zhí)行UIViewKeyframeAnimationOptionCalculationModeCubic//運(yùn)算模式 :平滑UIViewKeyframeAnimationOptionCalculationModeCubicPaced//運(yùn)算模式 :平滑均勻
各種運(yùn)算模式的直觀(guān)比較如下圖:

圖片來(lái)源網(wǎng)絡(luò).png
增加關(guān)鍵幀的方法:
[UIViewaddKeyframeWithRelativeStartTime:(double)//動(dòng)畫(huà)開(kāi)始的時(shí)間(占總時(shí)間的比例)relativeDuration:(double)//動(dòng)畫(huà)持續(xù)時(shí)間(占總時(shí)間的比例)animations:^{//執(zhí)行的動(dòng)畫(huà)}];
6、轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
6.1 從舊視圖轉(zhuǎn)到新視圖的動(dòng)畫(huà)效果
[UIViewtransitionFromView:(nonnullUIView *)toView:(nonnullUIView *)duration:(NSTimeInterval)options:(UIViewAnimationOptions)completion:^(BOOLfinished){? ? ? ? ? ? ? ? ? ? //動(dòng)畫(huà)執(zhí)行完畢后的操作 }];
在該動(dòng)畫(huà)過(guò)程中,fromView 會(huì)從父視圖中移除,并講 toView 添加到父視圖中,注意轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的作用對(duì)象是父視圖(過(guò)渡效果體現(xiàn)在父視圖上)。
調(diào)用該方法相當(dāng)于執(zhí)行下面兩句代碼:
[fromView.superviewaddSubview:toView];[fromViewremoveFromSuperview];
6.2 單個(gè)視圖的過(guò)渡效果
[UIViewtransitionWithView:(nonnullUIView *)duration:(NSTimeInterval)options:(UIViewAnimationOptions)animations:^{? ? ? ? ? ? ? ? //執(zhí)行的動(dòng)畫(huà) }? ? ? ? ? ? ? ? completion:^(BOOLfinished){? ? ? ? ? ? ? ? //動(dòng)畫(huà)執(zhí)行完畢后的操作 }];
1、普通動(dòng)畫(huà)
下面三段代碼都實(shí)現(xiàn)了相同的視圖frame的變化,不同之處只在于其延遲時(shí)間、過(guò)渡效果和結(jié)束回調(diào)。
- (void)blockAni1 {? ? [UIViewanimateWithDuration:1.0animations:^{self.cartCenter.frame=self.centerShow.frame;? ? }];}
- (void)blockAni2 {? ? [UIViewanimateWithDuration:1.0animations:^{self.cartCenter.frame=self.centerShow.frame;? ? } completion:^(BOOLfinished) {NSLog(@"動(dòng)畫(huà)結(jié)束");? ? }];}
- (void)blockAni3 {? ? [UIViewanimateWithDuration:1.0delay:1.0options:UIViewAnimationOptionCurveEaseInOutanimations:^{self.cartCenter.frame=self.centerShow.frame;? ? } completion:^(BOOLfinished) {NSLog(@"動(dòng)畫(huà)結(jié)束");? ? }];}
動(dòng)畫(huà)效果:

NormalAni.gif
2、Spring動(dòng)畫(huà)
- (void)blockAni4 {? ? [UIViewanimateWithDuration:1.0delay:0.f usingSpringWithDamping:0.5initialSpringVelocity:5.0options:UIViewAnimationOptionCurveLinearanimations:^{self.cartCenter.frame=self.centerShow.frame;? ? } completion:^(BOOLfinished) {NSLog(@"動(dòng)畫(huà)結(jié)束");? ? }];}
動(dòng)畫(huà)效果:

SpringAni.gif
3、Keyframes動(dòng)畫(huà)
這里以實(shí)現(xiàn)視圖背景顏色變化(紅-綠-藍(lán)-紫)的過(guò)程來(lái)演示關(guān)鍵幀動(dòng)畫(huà)。
- (void)blockAni5 {? ? self.centerShow.image = nil;? ? [UIView animateKeyframesWithDuration:9.0delay:0.foptions:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{? ? ? ? [UIView addKeyframeWithRelativeStartTime:0.frelativeDuration:1.0/4animations:^{? ? ? ? ? ? self.centerShow.backgroundColor = [UIColor colorWithRed:0.9475green:0.1921blue:0.1746alpha:1.0];? ? ? ? }];? ? ? ? [UIView addKeyframeWithRelativeStartTime:1.0/4relativeDuration:1.0/4animations:^{? ? ? ? ? ? self.centerShow.backgroundColor = [UIColor colorWithRed:0.1064green:0.6052blue:0.0334alpha:1.0];? ? ? ? }];? ? ? ? [UIView addKeyframeWithRelativeStartTime:2.0/4relativeDuration:1.0/4animations:^{? ? ? ? ? ? self.centerShow.backgroundColor = [UIColor colorWithRed:0.1366green:0.3017blue:0.8411alpha:1.0];? ? ? ? }];? ? ? ? [UIView addKeyframeWithRelativeStartTime:3.0/4relativeDuration:1.0/4animations:^{? ? ? ? ? ? self.centerShow.backgroundColor = [UIColor colorWithRed:0.619green:0.037blue:0.6719alpha:1.0];? ? ? ? }];? ? } completion:^(BOOL finished) {? ? ? ? NSLog(@"動(dòng)畫(huà)結(jié)束");? ? }];}
動(dòng)畫(huà)效果:

KeyFramesAni.gif
4、轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
4.1 單個(gè)視圖的過(guò)渡效果
- (void)blockAni6 {? ? [UIViewtransitionWithView:self.centerShowduration:1.0options:UIViewAnimationOptionTransitionCrossDissolveanimations:^{self.centerShow.image= [UIImageimageNamed:@"Service"];? ? } completion:^(BOOLfinished) {NSLog(@"動(dòng)畫(huà)結(jié)束");? ? }];}
動(dòng)畫(huà)效果:

TransitionAni.gif
4.2 從舊視圖轉(zhuǎn)到新視圖的動(dòng)畫(huà)效果
- (void)blockAni7 {UIImageView* newCenterShow = [[UIImageViewalloc]initWithFrame:self.centerShow.frame];? ? newCenterShow.image= [UIImageimageNamed:@"Service"];? ? [UIViewtransitionFromView:self.centerShowtoView:newCenterShow duration:1.0options:UIViewAnimationOptionTransitionFlipFromLeftcompletion:^(BOOLfinished) {NSLog(@"動(dòng)畫(huà)結(jié)束");? ? }];}
動(dòng)畫(huà)效果:

ScreenTransitionAni.gif