最近在做iOS
界面轉(zhuǎn)場(chǎng)的動(dòng)畫(huà),寫(xiě)完轉(zhuǎn)場(chǎng)入口后基本元素還是回歸到我們常用的基本動(dòng)畫(huà)代碼,有關(guān)動(dòng)畫(huà)的帖子網(wǎng)絡(luò)上一搜一大把,而且介紹的都比較不錯(cuò),本文還是不厭其煩的對(duì)基本常用到的動(dòng)畫(huà)做一個(gè)詳細(xì)統(tǒng)一介紹和總結(jié),主要記錄下自己學(xué)習(xí)動(dòng)畫(huà)的點(diǎn)。
在App
開(kāi)發(fā)中幾乎都使用過(guò)動(dòng)畫(huà),絢麗的動(dòng)畫(huà)效果也是iOS
系統(tǒng)的一大亮點(diǎn);使用動(dòng)畫(huà)可以讓我們的App
非常炫酷,同時(shí)更重要的是大大的提升了用戶體驗(yàn)。那動(dòng)畫(huà)是什么呢?動(dòng)畫(huà)實(shí)質(zhì)其實(shí)就是一張張連續(xù)的圖片在一定的時(shí)間內(nèi)連續(xù)展示出來(lái)的效果。打個(gè)比方說(shuō):把很多張慢動(dòng)作的武打戲圖片連續(xù)播放合成一段小視頻。動(dòng)畫(huà)就是和這個(gè)視頻是一樣的效果!實(shí)質(zhì)就是產(chǎn)生連續(xù)的假象來(lái)欺騙人的眼睛,從而達(dá)到動(dòng)畫(huà)的效果!
iOS
開(kāi)發(fā)中,常用的動(dòng)畫(huà)有UIView動(dòng)畫(huà)
和核心動(dòng)畫(huà)
,很多書(shū)籍上有區(qū)分隱式動(dòng)畫(huà)
和顯示動(dòng)畫(huà)
以及其他動(dòng)畫(huà)的
詳細(xì)介紹,下文中會(huì)簡(jiǎn)單講到,如需要詳細(xì)介紹的可以去查找下相關(guān)資料。UIView動(dòng)畫(huà)
和核心動(dòng)畫(huà)
一圖是iOS
提供的動(dòng)畫(huà)API
框架結(jié)構(gòu),UIView
動(dòng)畫(huà):UIKit / AppKit
;核心動(dòng)畫(huà)包括:CATransaction
動(dòng)畫(huà)以及Core Animation
等框架,Core Animation
等框架位于UIKit
的下一層,相比UIView
的動(dòng)畫(huà),它可以實(shí)現(xiàn)更復(fù)雜的動(dòng)畫(huà)效果。下面我們先來(lái)介紹下iOS中簡(jiǎn)單常用的UIView
動(dòng)畫(huà)的內(nèi)容及其使用。
Tip:在模擬器上運(yùn)行時(shí),我們可以點(diǎn)擊菜單欄
Debug
下的Slow Animation
或者快捷鍵command+T
,來(lái)放慢App
中的動(dòng)畫(huà)效果并分析動(dòng)畫(huà)內(nèi)容。
一、UIView類實(shí)現(xiàn)的常用動(dòng)畫(huà)方法
對(duì)于每一個(gè)UIView
都有一個(gè)Layer
屬性,把這個(gè)Layer
且稱作為RootLayer
,而不是UIView
的RootLayer
的叫做非RootLayer
。我們對(duì)UIView
的屬性修改時(shí)時(shí)不會(huì)產(chǎn)生默認(rèn)動(dòng)畫(huà),而對(duì)非RootLayer
屬性直接修改會(huì)產(chǎn)生動(dòng)畫(huà),這個(gè)默認(rèn)動(dòng)畫(huà)的時(shí)間缺省值是0.25s,這個(gè)動(dòng)畫(huà)也稱作隱式動(dòng)畫(huà)。UIView
默認(rèn)情況下禁止了RootLayer
的隱式動(dòng)畫(huà),但是在UIVIew
的animation block
方法中又重新啟用了它們。(有關(guān)UIView
和CALayer
介紹稍后詳說(shuō))
需要注意的是:使用UIView
的動(dòng)畫(huà)方法,只能針對(duì)動(dòng)畫(huà)屬性修改才能產(chǎn)生動(dòng)畫(huà)效果。UIView
支持的動(dòng)畫(huà)屬性有frame
、bounds
、center
、transform
、alpha
、backgroundColor
、contentStretch
等。
第一種:使用UIView的 [beginAnimations … commitAniamtions] 模式來(lái)實(shí)現(xiàn)動(dòng)畫(huà)
先過(guò)一遍系統(tǒng)的API
方法:
//開(kāi)始動(dòng)畫(huà)
+ (void)beginAnimations:(NSString *)animationID context:(void *)context;
//提交動(dòng)畫(huà)
+ (void)commitAnimations;
//設(shè)置動(dòng)畫(huà)代理對(duì)象
+ (void)setAnimationDelegate:(id)delegate;
//當(dāng)動(dòng)畫(huà)即將開(kāi)始時(shí)執(zhí)行指定的SEL方法《必須要先設(shè)置動(dòng)畫(huà)代理》
+ (void)setAnimationWillStartSelector:(SEL)selector
//當(dāng)動(dòng)畫(huà)結(jié)束時(shí)執(zhí)行指定的SEL方法《必須要先設(shè)置動(dòng)畫(huà)代理》
+ (void)setAnimationDidStopSelector:(SEL)selector;
//設(shè)置動(dòng)畫(huà)的持續(xù)時(shí)間,單位為:秒
+ (void)setAnimationDuration:(NSTimeInterval)duration;
//設(shè)置動(dòng)畫(huà)延遲執(zhí)行,單位為:秒
+ (void)setAnimationDelay:(NSTimeInterval)delay;
//動(dòng)畫(huà)的開(kāi)始時(shí)間,默認(rèn)為:立即
+ (void)setAnimationStartDate:(NSDate *)startDate;
//動(dòng)畫(huà)的速度曲線控制
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
//動(dòng)畫(huà)的重復(fù)次數(shù)
+ (void)setAnimationRepeatCount:(float)repeatCount;
//如果設(shè)置為YES,代表動(dòng)畫(huà)每次重復(fù)執(zhí)行的效果會(huì)跟上一次相反
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
//設(shè)置視圖view的過(guò)渡效果,transition指定過(guò)渡類型,cache設(shè)置YES代表使用視圖緩存,性能較好
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
//當(dāng)設(shè)置的時(shí)候忽視所有屬性的改變
+ (void)setAnimationsEnabled:(BOOL)enabled;
這種動(dòng)畫(huà)的使用方法比較簡(jiǎn)單,將動(dòng)畫(huà)代碼寫(xiě)在begin
和commit
之間就完成了動(dòng)畫(huà)的編寫(xiě)
[UIView beginAnimations:@"animation" context:nil]; //準(zhǔn)備動(dòng)畫(huà)
// Code... 【在此處修改view的動(dòng)畫(huà)屬性,需注意:有些屬性不支持動(dòng)畫(huà)操作的】
[UIView commitAnimations]; //提交動(dòng)畫(huà)
我們舉個(gè)簡(jiǎn)單的透明度漸變的例子:
//獲取當(dāng)前視圖的上下文,在此處傳入上下文可以在代理方法中使用到
CGContextRef context = UIGraphicsGetCurrentContext();
//準(zhǔn)備編寫(xiě)動(dòng)畫(huà)代碼
[UIView beginAnimations:@"AlphaAnimation" context:context];
[UIView setAnimationDuration:0.5f];
[animationView setAlpha:0.0f];
[UIView commitAnimations];
第二種:使用UIView的block代碼塊調(diào)用動(dòng)畫(huà)
在iOS4的時(shí)候蘋果大量的添加了Block API
,之前的動(dòng)畫(huà)API
也不例外。使用動(dòng)畫(huà)的Block API
后,方便了動(dòng)畫(huà)嵌套使用,也讓我們的代碼更清晰,使用也更簡(jiǎn)單了!不多說(shuō)了,下面來(lái)介紹下Block
的內(nèi)容。
UIView
的block動(dòng)畫(huà)
方法中常見(jiàn)的參數(shù)介紹:
duration : 動(dòng)畫(huà)時(shí)長(zhǎng)
delay : 決定了動(dòng)畫(huà)在延遲多久之后執(zhí)行
options : 用來(lái)決定動(dòng)畫(huà)的展示方式,參照下面的枚舉參數(shù)說(shuō)明
animations : 具體動(dòng)畫(huà)內(nèi)容的代碼
completion : 動(dòng)畫(huà)結(jié)束后執(zhí)行的代碼塊
枚舉參數(shù)說(shuō)明:
enum {
//這部分是基礎(chǔ)屬性的設(shè)置
UIViewAnimationOptionLayoutSubviews = 1 << 0, //設(shè)置子視圖隨父視圖展示動(dòng)畫(huà)
UIViewAnimationOptionAllowUserInteraction = 1 << 1, //允許在動(dòng)畫(huà)執(zhí)行時(shí)用戶與其進(jìn)行交互
UIViewAnimationOptionBeginFromCurrentState = 1 << 2, //允許在動(dòng)畫(huà)執(zhí)行時(shí)執(zhí)行新的動(dòng)畫(huà)
UIViewAnimationOptionRepeat = 1 << 3, //設(shè)置動(dòng)畫(huà)循環(huán)執(zhí)行
UIViewAnimationOptionAutoreverse = 1 << 4, //設(shè)置動(dòng)畫(huà)反向執(zhí)行,必須和重復(fù)執(zhí)行一起使用
UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, //強(qiáng)制動(dòng)畫(huà)使用內(nèi)層動(dòng)畫(huà)的時(shí)間值
UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, //強(qiáng)制動(dòng)畫(huà)使用內(nèi)層動(dòng)畫(huà)曲線值
UIViewAnimationOptionAllowAnimatedContent = 1 << 7, //設(shè)置動(dòng)畫(huà)視圖實(shí)時(shí)刷新
UIViewAnimationOptionShowHideTransitionViews = 1 << 8, //設(shè)置視圖切換時(shí)隱藏,而不是移除
UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, //
//這部分屬性設(shè)置動(dòng)畫(huà)播放的線性效果
UIViewAnimationOptionCurveEaseInOut = 0 << 16, //淡入淡出 首末減速
UIViewAnimationOptionCurveEaseIn = 1 << 16, //淡入 初始減速
UIViewAnimationOptionCurveEaseOut = 2 << 16, //淡出 末尾減速
UIViewAnimationOptionCurveLinear = 3 << 16, //線性 勻速執(zhí)行
//這部分設(shè)置UIView切換效果
UIViewAnimationOptionTransitionNone = 0 << 20,
UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, //從左邊切入
UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, //從右邊切入
UIViewAnimationOptionTransitionCurlUp = 3 << 20, //從上面立體進(jìn)入
UIViewAnimationOptionTransitionCurlDown = 4 << 20, //從下面立體進(jìn)入
UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, //溶解效果
UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, //從上面切入
UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, //從下面切入
};
注意:此類型可以使用“|”進(jìn)行多項(xiàng)一起使用
①、UIView實(shí)現(xiàn)的動(dòng)畫(huà)最常用普通的方法
系統(tǒng)API
的說(shuō)明和功能介紹:
//一般的動(dòng)畫(huà)
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion;
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion;
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void(^)(void))animations;
常用的動(dòng)畫(huà)使用也比較簡(jiǎn)單,把之前寫(xiě)在begin
和commit
之間的代碼移動(dòng)到block
中就完成動(dòng)畫(huà)編寫(xiě),如:
[UIView animateWithDuration:4.0 // 動(dòng)畫(huà)時(shí)長(zhǎng)
delay:2.0 // 動(dòng)畫(huà)延遲
options:UIViewAnimationOptionCurveEaseIn // 動(dòng)畫(huà)過(guò)渡效果
animations:^{ //code... 動(dòng)畫(huà)內(nèi)容 }
completion:^(BOOL finished) { //code... 動(dòng)畫(huà)完成后執(zhí)行 }];
同樣的,還以透明度漸變?yōu)槔樱?/p>
[UIView animateWithDuration:0.5 // 動(dòng)畫(huà)時(shí)長(zhǎng)
delay:0.0 // 動(dòng)畫(huà)延遲
options:UIViewAnimationOptionCurveEaseIn // 動(dòng)畫(huà)過(guò)渡效果
animations:^{ [animationView setAlpha:0.0f]; }
completion:^(BOOL finished) { //code... 動(dòng)畫(huà)完成后執(zhí)行 }];
②、UIView的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)類方法
系統(tǒng)API
的說(shuō)明和功能介紹:
//轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion;
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void(^)(BOOL finished))completion;
/*第二個(gè)方法調(diào)用完畢后,還需要處理View的層次關(guān)系,添加toView到父視圖并移除fromView*/
轉(zhuǎn)場(chǎng)動(dòng)畫(huà)換個(gè)卡牌翻轉(zhuǎn)的例子,示例代碼如:
imageView.image = [UIImage imageNamed:@"背景圖片"];
[UIView transitionWithView:imageView
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ imageView.image = [UIImage imageNamed:@"內(nèi)容圖片"]; }
completion:^(BOOL finished) { //code... 動(dòng)畫(huà)完成后執(zhí)行 }];
③、UIView的彈簧動(dòng)畫(huà)類方法(iOS 7后添加的API)
這個(gè)方法是iOS7
之后的一個(gè)新方法,通過(guò)這個(gè)方法,可以方便的制作出彈簧振動(dòng)效果的動(dòng)畫(huà),這個(gè)方法的核心是兩個(gè)阻尼參數(shù)。
彈簧動(dòng)畫(huà)API
的說(shuō)明和功能介紹:
//彈簧的彈性動(dòng)畫(huà)(iOS7之后新加的方法)
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion;
動(dòng)畫(huà)方法中的新參數(shù):
usingSpringWithDamping : 取值范圍[0.0~1.0],數(shù)值越小振動(dòng)幅度越大
initialSpringVelocity : 初始速度,數(shù)值越大開(kāi)始移動(dòng)越快
基本寫(xiě)法及示例代碼:
[UIView animateWithDuration:4.0 // 動(dòng)畫(huà)時(shí)長(zhǎng)
delay:0.0 // 動(dòng)畫(huà)延遲
usingSpringWithDamping:1.0 // 類似彈簧振動(dòng)效果 0~1
initialSpringVelocity:5.0 // 初始速度
options:UIViewAnimationOptionCurveEaseInOut // 動(dòng)畫(huà)過(guò)渡效果
animations:^{ // code... }
completion:^(BOOL finished) { // code... }];
④、UIView的關(guān)鍵幀動(dòng)畫(huà)類方法(iOS 7后添加的API)
關(guān)鍵幀動(dòng)畫(huà)是指:給出整個(gè)動(dòng)畫(huà)過(guò)程中的幾個(gè)關(guān)鍵幀畫(huà)面信息,關(guān)鍵幀之間的過(guò)渡幀都由計(jì)算機(jī)自動(dòng)生成。
這個(gè)方法也是iOS7
之后的一個(gè)新方法,通過(guò)這個(gè)方法可以不需要去使用到核心動(dòng)畫(huà)(Core Animation)
就能創(chuàng)建關(guān)鍵幀的更多更復(fù)雜的動(dòng)畫(huà)效果。
關(guān)鍵幀動(dòng)畫(huà)API
的說(shuō)明和功能介紹:
//創(chuàng)建關(guān)鍵幀方法
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion;
//添加關(guān)鍵幀
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void(^)(void))animations;
以簡(jiǎn)單的單次抖動(dòng)作為示例:(這寫(xiě)復(fù)雜了僅作參考)
__weak UIView *weakView = self.animationView;
void(^animations)(void) = ^{
//向右旋轉(zhuǎn)
void(^leftCallblock)(void) = ^{
weakView.transform = CGAffineTransformRotate(weakView.transform,M_PI/9);
};
[UIView addKeyframeWithRelativeStartTime:0.0 //相對(duì)于6秒所開(kāi)始的時(shí)間(第0秒開(kāi)始動(dòng)畫(huà))
relativeDuration:1/4.0 //相對(duì)于6秒動(dòng)畫(huà)的持續(xù)時(shí)間(動(dòng)畫(huà)持續(xù)2秒)
animations:leftCallblock];
//復(fù)原
void(^resetblock)(void) = ^{
weakView.transform = CGAffineTransformIdentity;
};
[UIView addKeyframeWithRelativeStartTime:1/4.0 //相對(duì)于6秒所開(kāi)始的時(shí)間(第0秒開(kāi)始動(dòng)畫(huà))
relativeDuration:1/4.0 //相對(duì)于6秒動(dòng)畫(huà)的持續(xù)時(shí)間(動(dòng)畫(huà)持續(xù)2秒)
animations:resetblock];
//向左旋轉(zhuǎn)
void(^rightCallblock)(void) = ^{
weakView.transform = CGAffineTransformRotate(weakView.transform,-M_PI/9);
};
[UIView addKeyframeWithRelativeStartTime:2/4.0 //相對(duì)于6秒所開(kāi)始的時(shí)間(第0秒開(kāi)始動(dòng)畫(huà))
relativeDuration:1/4.0 //相對(duì)于6秒動(dòng)畫(huà)的持續(xù)時(shí)間(動(dòng)畫(huà)持續(xù)2秒)
animations:rightCallblock];
//復(fù)原
[UIView addKeyframeWithRelativeStartTime:3/4.0 //相對(duì)于6秒所開(kāi)始的時(shí)間(第0秒開(kāi)始動(dòng)畫(huà))
relativeDuration:1/4.0 //相對(duì)于6秒動(dòng)畫(huà)的持續(xù)時(shí)間(動(dòng)畫(huà)持續(xù)2秒)
animations:resetblock];
};
[UIView animateKeyframesWithDuration:0.5f
delay:0.0f
options:UIViewKeyframeAnimationOptionCalculationModeLinear
animations:animations
completion:NULL];
關(guān)鍵幀新加的枚舉參數(shù):
enum {
UIViewKeyframeAnimationOptionCalculationModeLinear = 0 << 10, // default
UIViewKeyframeAnimationOptionCalculationModeDiscrete = 1 << 10,
UIViewKeyframeAnimationOptionCalculationModePaced = 2 << 10,
UIViewKeyframeAnimationOptionCalculationModeCubic = 3 << 10,
UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10
};
這里的示例中使用到了transform
屬性,額外再記錄下transform
屬性
從transform
提供的API
來(lái)說(shuō)主要體現(xiàn)在縮放、位移和旋轉(zhuǎn)三個(gè)方面,transform
的運(yùn)算是按照矩陣(3x3矩陣)進(jìn)行運(yùn)算的,這樣會(huì)減少運(yùn)算量,提高效率。
關(guān)于transform和矩陣的詳細(xì)內(nèi)容請(qǐng)參考:iOS開(kāi)發(fā)筆記之transform
//用來(lái)連接兩個(gè)變換效果并返回。返回的t = t1 * t2
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);
//矩陣初始值。[ 1 0 0 1 0 0 ]
CGAffineTransformIdentity;
//自定義矩陣變換,需要掌握矩陣變換的知識(shí)才知道怎么用。參照上面推薦的原理鏈接
CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty);
/*
旋轉(zhuǎn)視圖
1.當(dāng)參數(shù)x>0 && x<=M_PI時(shí),為順時(shí)針
2.當(dāng)參數(shù)x>-M_PI && x<0時(shí),為逆時(shí)針
3.若參數(shù)x<M_PI || x>2.0*M_PI時(shí),則旋轉(zhuǎn)方向等同于x%2的旋轉(zhuǎn)方向
總結(jié):旋轉(zhuǎn)方向就是向最短路徑方向旋轉(zhuǎn)
*/
CGAffineTransformMakeRotation(CGFloat angle);
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);
?
//縮放視圖。等同于CGAffineTransformScale(self.transform, sx, sy)
CGAffineTransformMakeScale(CGFloat sx, CGFloat sy);
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);
//平移視圖。等同于CGAffineTransformTranslate(self.transform, tx, ty)
CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty);
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty);
二、核心動(dòng)畫(huà)(Core Animation框架)
Core Animation
框架是基于OpenGL
與Core Graphics
圖像處理框架的一個(gè)跨平臺(tái)的動(dòng)畫(huà)框架。在真實(shí)的開(kāi)發(fā)中,一般還是主要使用UIView封裝的動(dòng)畫(huà),而很少使用Core Animation
的動(dòng)畫(huà);使用UIView
和CALayer
都能實(shí)現(xiàn)動(dòng)畫(huà)效果,但是當(dāng)一般的UIView動(dòng)畫(huà)不能滿足我們的需求時(shí),就需要使用核心動(dòng)畫(huà)來(lái)實(shí)現(xiàn)。核心動(dòng)畫(huà)是直接作用在CALayer
上的動(dòng)畫(huà),而非UIView
對(duì)象;所以介紹核心動(dòng)畫(huà)前,我們先了解下UIView
和CALayer
之間的聯(lián)系以及區(qū)別。
關(guān)聯(lián)引申??????????
CALayer
是屬于Core Animation
部分的內(nèi)容,包含在QuartzCore
框架中,這是一個(gè)跨平臺(tái)的框架,既可以用在iOS
中又可以用在Mac OS X
中;實(shí)際上CALayer
只是捕獲App
所提供的內(nèi)容,并緩存成bitmap
(位圖),當(dāng)任何與CALayer
關(guān)聯(lián)的屬性值發(fā)生變化時(shí),Core Animation
就會(huì)將新的bitmap
(位圖)傳給繪圖硬件,并根據(jù)新的bitmap
(位圖)更新顯示。
UIView
是iOS
系統(tǒng)中界面元素的基礎(chǔ),所有的界面元素都是繼承自UIView
類,它真正的繪圖部分,是由一個(gè)CALayer
類來(lái)管理。每個(gè)UIView
默認(rèn)就包含一個(gè)CALayer
屬性,UIView
就像是一個(gè)CALayer
的管理器,在View
顯示的時(shí)候,UIView
做為CALayer
的CALayerDelegate
,UIView
的顯示內(nèi)容由內(nèi)部的CALayer
來(lái)顯示。訪問(wèn)UIView
的與繪圖和跟坐標(biāo)有關(guān)的屬性,例如frame
、bounds
等,實(shí)際上內(nèi)部都是在訪問(wèn)它所包含的CALayer
的相關(guān)屬性。有人說(shuō)UIView
就像一個(gè)畫(huà)板,而layer
就像畫(huà)布,一個(gè)畫(huà)板上可以有很多塊畫(huà)布,但是畫(huà)布不能有畫(huà)板。
CALayer
和UIView
類似都擁有自己的樹(shù)形結(jié)構(gòu),UIView
包含很多subView
,而CALayer
是可以包含subLayer
的,因此形成了圖層樹(shù),CALayer
層是可以嵌套的,可以向它的layer
上添加subLayer
,來(lái)完成某些特殊內(nèi)容的顯示。
UIView
與CALayer
的主要區(qū)別
1、UIView
是可以響應(yīng)事件的,但是CALayer
不能響應(yīng)事件
2、UIView
主要負(fù)責(zé)管理顯示內(nèi)容,而CALayer
主要負(fù)責(zé)渲染和呈現(xiàn)。如果沒(méi)有CALayer
,我們是看不到內(nèi)容的。
3、CALayer
內(nèi)部維護(hù)著三分layer tree
,分別是presentLayer tree
(動(dòng)畫(huà)樹(shù)),modeLayer tree
(模型樹(shù)),render tree
(渲染樹(shù)),在做iOS
動(dòng)畫(huà)的時(shí)候,我們修改動(dòng)畫(huà)的屬性,在動(dòng)畫(huà)的其實(shí)是CALayer
的present Layer
的屬性值,而最終展示在界面上的其實(shí)是提供UIView
的modelLayer
。
CALayer
核心動(dòng)畫(huà)與UIView
動(dòng)畫(huà)的區(qū)別:
UIView
封裝的動(dòng)畫(huà)執(zhí)行完畢之后不會(huì)反彈,CALayer
核心動(dòng)畫(huà)則會(huì);另外UIView
的動(dòng)畫(huà)期間可以處理用戶事件,CALayer
核心動(dòng)畫(huà)則不能。例如:如果是通過(guò)CALayer
核心動(dòng)畫(huà)改變layer
的位置狀態(tài),表面上看雖然已經(jīng)改變了,但是實(shí)際上它的位置是沒(méi)有改變的。
核心動(dòng)畫(huà)官方文檔地址:Core Animation Guide
核心動(dòng)畫(huà)是
iOS
和OS X
上的圖形渲染和動(dòng)畫(huà)基礎(chǔ)設(shè)施,用于為應(yīng)用程序的視圖和其他視覺(jué)元素設(shè)置動(dòng)畫(huà)。使用核心動(dòng)畫(huà),為您繪制每幅畫(huà)面所需的大部分工作。所有你需要做的是配置一些動(dòng)畫(huà)參數(shù)(如開(kāi)始和結(jié)束點(diǎn)),并告訴核心動(dòng)畫(huà)開(kāi)始。核心動(dòng)畫(huà)完成其余的工作,將大部分實(shí)際的繪圖工作交給板載圖形硬件,以加速渲染。這種自動(dòng)圖形加速可以實(shí)現(xiàn)高幀速率和平滑動(dòng)畫(huà),而不會(huì)對(duì)CPU
造成負(fù)擔(dān),并減慢應(yīng)用程序的速度。
核心動(dòng)畫(huà)的繼承結(jié)構(gòu)
CAAnimation <CAMediaTiming> {
CATransition
CAAnimationGroup
CAPropertyAnimation {
CABasicAnimation {
CASpringAnimation (iOS 9才開(kāi)始支持)
}
CAKeyframeAnimation
}
}
核心動(dòng)畫(huà)的繼承關(guān)系與常用屬性如下圖
CAAnimation
是所有動(dòng)畫(huà)對(duì)象的父類,它遵守CAMediaTiming
協(xié)議,負(fù)責(zé)控制動(dòng)畫(huà)的時(shí)間、速度和時(shí)間曲線等等,是一個(gè)抽象類,不能直接使用。CAPropertyAnimation
是CAAnimation
的子類,它支持動(dòng)畫(huà)地顯示圖層的KeyPath
,也不能直接使用。
iOS9.0
之后新增CASpringAnimation
類,它實(shí)現(xiàn)彈簧效果的動(dòng)畫(huà)是CABasicAnimation的子類
。
綜上,核心動(dòng)畫(huà)類中可以直接使用的類有:CATransition
、CABasicAnimation
、CASpringAnimation
、CAKeyframeAnimation
、CAAnimationGroup
五個(gè)類。
①、CAAnimation
的屬性介紹:注意CAAnimation
不能直接使用
//動(dòng)畫(huà)開(kāi)始結(jié)束的回調(diào)代理
@property (nullable, assgin) id delegate;
//動(dòng)畫(huà)完成后是否移除動(dòng)畫(huà),默認(rèn)為YES
@property (getter=isRemovedOnCompletion) BOOL removedOnCompletion;
//動(dòng)畫(huà)的動(dòng)作規(guī)則,包含勻速、慢進(jìn)快出、快進(jìn)慢出、慢進(jìn)慢出<中間加速>、默認(rèn)
@property (nullable, strong) CAMediaTimingFunction *timingFunction;
+ (id)animation; //類方法創(chuàng)建動(dòng)畫(huà)對(duì)象
注意:
timingFunction 可通過(guò)系統(tǒng)提供的API自定義喜歡的曲線函數(shù)來(lái)處理動(dòng)畫(huà)
動(dòng)畫(huà)的removedOnCompletion屬性需要配合fillMode來(lái)使用。默認(rèn)為YES,fillMode不可用
CAAnimation
的協(xié)議屬性介紹:
//開(kāi)始時(shí)間,例如:CACurrentMediaTime() + x 其中x為延遲時(shí)間
@property CFTimeInterval beginTime;
//動(dòng)畫(huà)執(zhí)行時(shí)間,與speed有關(guān)系,默認(rèn)為1.0,如果speed=2.0,那么執(zhí)行時(shí)間為:durantion*(1.0/2.0)
@property CFTimeInterval duration;
//動(dòng)畫(huà)執(zhí)行速度
@property float speed;
//動(dòng)畫(huà)的時(shí)間延遲,默認(rèn)為0
@property CFTimeInterval timeOffset;
//重復(fù)執(zhí)行次數(shù)
@property float repeatCount;
//重復(fù)執(zhí)行時(shí)間,此屬性優(yōu)先級(jí)大于repeatCount
@property CFTimeInterval repeatDuration;
//是否自動(dòng)翻轉(zhuǎn)動(dòng)畫(huà),默認(rèn)為NO,如果為YES,那么整個(gè)動(dòng)畫(huà)效果為A->B->A
@property BOOL autoreverses;
/*動(dòng)畫(huà)的填充方式,
動(dòng)畫(huà)結(jié)束后回到準(zhǔn)備狀態(tài)(kCAFillModeForwards)、
動(dòng)畫(huà)結(jié)束后保持最后狀態(tài)(kCAFillModeBackwards)、
動(dòng)畫(huà)結(jié)束后回到準(zhǔn)備狀態(tài)并保持最后狀態(tài)(kCAFillModelBoth)、
執(zhí)行完成移除動(dòng)畫(huà)(kCAFillModeRemoved)
*/
@property (copy) NSString *fillMode;
動(dòng)畫(huà)代理對(duì)象協(xié)議
//動(dòng)畫(huà)開(kāi)始時(shí)回調(diào)此方法
- (void)animationDidStart:(CAAnimation *)animation;
//動(dòng)畫(huà)結(jié)束時(shí)回調(diào)此方法
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag;
②、CATransition
轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的使用
CATransition
的屬性介紹:
@property (copy) NSString *type; //轉(zhuǎn)場(chǎng)類型
@property (nullable, copy) NSString *subtype; //轉(zhuǎn)場(chǎng)方向
@property float startProgress; //開(kāi)始進(jìn)度,默認(rèn)0.0,如果為0.4則直接從0.4開(kāi)始動(dòng)畫(huà)
@property float endProgress; //結(jié)束進(jìn)度,默認(rèn)1.0,如果為0.6則直接到0.6結(jié)束動(dòng)畫(huà)
@property (nullable, strong) id filter; //開(kāi)始進(jìn)度
轉(zhuǎn)場(chǎng)類型有私有API
和非私有API
兩種
可供type選擇的值有以下內(nèi)容(轉(zhuǎn)場(chǎng)類型)
{
//公開(kāi)API轉(zhuǎn)場(chǎng)種類
kCATransitionFade 漸變
kCATransitionMoveIn 覆蓋
kCATransitionPush 推出
kCATransitionReveal 揭開(kāi)
//私有API轉(zhuǎn)場(chǎng)種類
@"cube" 立方體翻轉(zhuǎn)效果
@"oglFlip" 翻轉(zhuǎn)效果
@"suckEffect" 收縮效果,動(dòng)畫(huà)方向不可控
@"rippleEffect" 水滴波紋效果,動(dòng)畫(huà)方向不可控
@"pageCurl" 向上翻頁(yè)效果
@"pageUnCurl" 向下翻頁(yè)效果
@"cameralIrisHollowOpen" 攝像頭打開(kāi)效果
@"cameralIrisHollowClose" 攝像頭關(guān)閉效果
};
可供subtype選擇的值有以下內(nèi)容(轉(zhuǎn)場(chǎng)方向)
{
kCATransitionFromRight 從右開(kāi)始
kCATransitionFromLeft 從左開(kāi)始
kCATransitionFromTop 從上開(kāi)始
kCATransitionFromBottom 從下開(kāi)始
};
轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的基本寫(xiě)法及示例代碼:(以淡入淡出的動(dòng)畫(huà)效果為例)
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.subType = kCATransitionFromLeft;
animation.duration = 0.5f;
self.imageView.image = [UIImage imageNamed:@"動(dòng)畫(huà)后的圖片"];
[self.imageView.layer addAnimation:animation forKey:@"transition"];
③、CAPropertyAnimation的子類CABasicAnimation的使用
CAPropertyAnimation
的子類初始化方法
//通過(guò)key創(chuàng)建一個(gè)CAPropertyAnimation對(duì)象
+ (id)animationWithKeyPath:(NSString *)path;
注意:path可以設(shè)置動(dòng)畫(huà)的屬性列表
CATransform3D {
旋轉(zhuǎn)
rotation
transform.rotation.x
transform.rotation.y
transform.rotation.z
縮放
scale
transform.scale.x
transform.scale.y
transform.scale.z
平移
translation
transform.translation.x
transform.translation.y
transform.translation.z
}
CGPoint {
position
position.x
position.y
}
CGRect {
bounds
bounds.size
bounds.size.width
bounds.size.height
bounds.origin
bounds.origin.x
bounds.origin.y
}
property {
opacity
backgroundColor
cornerRadius
boarderWidth
contents
SHadow {
shadowColor
shadowOffset
shadowOpacity
shadowRadius
}
}
注意:CAPropertyAnimation是抽象類,不能直接使用,只能使用子類
CABasicAnimation
屬性介紹:
@property (nullable, strong) id fromValue; //開(kāi)始值
@property (nullable, strong) id toValue; //結(jié)束值
@property (nullable, strong) id byValue; //偏移值
CABasicAnimation
屬性之間的規(guī)則:
1、fromValue和toValue不為空,動(dòng)畫(huà)的效果會(huì)從fromValue的值變化到toValue
2、fromValue和byValue不為空,動(dòng)畫(huà)的效果將會(huì)從fromValue變化到fromValue+byValue
3、toValue和byValue都不為空,動(dòng)畫(huà)的效果將會(huì)從toValue-byValue變化到toValue
4、僅fromValue的值不為空,動(dòng)畫(huà)的效果將會(huì)從fromValue的值變化到當(dāng)前的狀態(tài)
5、僅toValue的值不為空,動(dòng)畫(huà)的效果將會(huì)從當(dāng)前狀態(tài)的值變化到toValue的值
6、僅byValue的值不為空,動(dòng)畫(huà)的效果將會(huì)從當(dāng)前的值變化到(當(dāng)前狀態(tài)的值+byValue)的值
CABasicAnimation
動(dòng)畫(huà)的基本寫(xiě)法及示例代碼:(以淡入淡出的動(dòng)畫(huà)效果為例)
CABasicAnimation *animation = nil;
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
[animation setFromValue:@1.0];
[animation setToValue:@0.1];
[animation setDelegate:self];
[animation setDuration:0.25];
[animation setRemovedOnCompletion:NO];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setAutoreverses:YES];
[animation setFillMode:kCAFillModeBoth];
[animationView.layer addAnimation:animation forKey:@"animation"];
④、CABasicAnimation的子類CASpringAnimation的使用
CASpringAnimation
屬性介紹:
@property CGFloat mass; //質(zhì)量,振幅與質(zhì)量成反比
@property CGFloat stiffness; //剛度系數(shù),值越大,形變產(chǎn)生的力越大
@property CGFloat damping; //阻尼系數(shù),阻止彈簧伸縮的系數(shù),值越大,停止越快
@property CGFloat initialVelocity; //初始速率,速率為正數(shù)時(shí)速度與運(yùn)動(dòng)方向一致,為負(fù)數(shù)時(shí),速度與運(yùn)動(dòng)方向相反
@property (readonly) CFTimeInterval settlingDuration; //結(jié)算時(shí)間,只讀。返回彈簧動(dòng)畫(huà)到停止時(shí)的估算時(shí)間
CASpringAnimation
動(dòng)畫(huà)的基本寫(xiě)法及示例代碼:
CASpringAnimation *spring = [CASpringAnimation animationWithKeyPath:@"position.y"];
spring.damping = 5;
spring.stiffness = 100;
spring.mass = 1;
spring.initialVelocity = 0;
spring.duration = spring.settlingDuration;
spring.formValue = @(animationView.cemter.y);
spring.toValue = @(animationView.center.y+(button.selected?100:-100));
spring.fillMode = kCAFillModeForwards;
[animationView.layer addAnimation:spring forKey:@"spring"];
⑤、CAPropertyAnimation的子類CAKeyframeAnimation的使用
CAKeyframeAnimation屬性介紹:
//關(guān)鍵幀值數(shù)組,一組變化值
@property (nullable, copy) NSArray *values;
//關(guān)鍵幀幀路徑,優(yōu)先級(jí)比values高
@property (nullable) CGPathRef path;
//每一幀對(duì)應(yīng)的時(shí)間,可以用來(lái)控制速度,它和每一幀對(duì)應(yīng),取值范圍:[0.0~1.0],不設(shè)置則默認(rèn)相等
@property (nullable, copy) NSArray *keyTimes;
//每一幀對(duì)應(yīng)的時(shí)間曲線函數(shù),也就是每一幀的運(yùn)動(dòng)節(jié)奏
@property (nullable, copy) NSArray *timingFunctions;
//動(dòng)畫(huà)的計(jì)算模式
@property (copy) NSString *calculationMode;
//動(dòng)畫(huà)的張力
@property (nullable, copy) NSArray *tensionValues;
//動(dòng)畫(huà)的連續(xù)性值
@property (nullable, copy) NSArray *continuityValues;
//動(dòng)畫(huà)的偏斜率
@property (nullable, copy) NSArray *biasValues;
//動(dòng)畫(huà)沿路徑旋轉(zhuǎn)方式,默認(rèn)為nil
@property (nullable, copy) NSString *rotationMode;
//動(dòng)畫(huà)的計(jì)算模式有
enum {
kCAAnimationLinear //默認(rèn)值,關(guān)鍵幀為座標(biāo)點(diǎn)的時(shí)候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算;
kCAAnimationDiscrete //離散的,也就是沒(méi)有補(bǔ)間動(dòng)畫(huà)
kCAAnimationPaced //平均
kCAAnimationCubic //對(duì)關(guān)鍵幀為座標(biāo)點(diǎn)的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計(jì)算
kCAAnimationCubicPaced //在kCAAnimationCubic的基礎(chǔ)上使得動(dòng)畫(huà)運(yùn)行變得均勻
};
注意:使用kCAAnimationPaced和kCAAnimationCubic以及kCAAnimationCubicPaced時(shí),keyTimes跟timeFunctions失效
//動(dòng)畫(huà)沿路徑旋轉(zhuǎn)方式
enum {
kCAAnimationRotateAuto //自動(dòng)旋轉(zhuǎn)
kCAAnimationRotateAutoReverse //自動(dòng)翻轉(zhuǎn)
};
CAKeyframeAnimation
動(dòng)畫(huà)的基本寫(xiě)法及示例代碼:
UIBezierPath *path = nil;
CAKeyframeAnimation *animation = nil;
path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 200, 100)];
animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[animation setPath:path.CGPath];
[animation setDuration:0.5];
[animation setRemovedOnCompletion:NO];
[animation setFillMode:kCAFillModeBoth];
[animationView.layer addAnimation:animation forKey:nil];
⑥、CAAnimationGroup的使用
CAAnimationGroup
屬性介紹:
//數(shù)組中存放CAAnimation的動(dòng)畫(huà)對(duì)象
@property (nullable, copy) NSArray *animations;
CAAnimationGroup
動(dòng)畫(huà)的基本寫(xiě)法及示例代碼:
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 320, 320));
CAKeyframeAnimation *position = [CAKeyframeAnimation animationWithKeyPath:@"position"];
[position setPath:path];
[position setDuration:3];
[position setRemovedOnCompletion:NO];
[position setFillMode:kCAFillModeForwards];
CGPathRelease(path);
CABasicAnimation *alpha = [CABasicAnimation animationWithKeyPath:@"opacity"];
[alpha setDuration:1.0];
[alpha setRepeatCount:3];
[alpha setAutoreverses:YES];
[alpha setFromValue:@1.0];
[alpha setDelegate:self];
[animation setToValue:@0.1];
CAAnimationGroup *group = [CAAnimationGroup animation];
[group setDuration:3.0];
[group setAnimations:@[position,alpha]];
[animationView.layer addAnimation:group forKey:nil];
三、核心動(dòng)畫(huà)和UIView動(dòng)畫(huà)的對(duì)比
核心動(dòng)畫(huà)
和UIView動(dòng)畫(huà)
的對(duì)比:UIView動(dòng)畫(huà)
可以看成是對(duì)核心動(dòng)畫(huà)
的封裝,和UIView動(dòng)畫(huà)
不同的是,通過(guò)核心動(dòng)畫(huà)
改變layer
的狀態(tài)(比如position
),動(dòng)畫(huà)執(zhí)行完畢后實(shí)際上是沒(méi)有改變的(表面上看起來(lái)已改變)。
給view
加上動(dòng)畫(huà),本質(zhì)上是對(duì)其layer
進(jìn)行操作,layer
包含了各種支持動(dòng)畫(huà)的屬性,動(dòng)畫(huà)則包含了屬性變化的值、變化的速度、變化的時(shí)間等等,兩者結(jié)合產(chǎn)生動(dòng)畫(huà)的過(guò)程。
總體來(lái)說(shuō)核心動(dòng)畫(huà)
的優(yōu)點(diǎn)有:
- 性能強(qiáng)大,使用硬件加速,可以同時(shí)向多個(gè)圖層添加不同的動(dòng)畫(huà)效果
- 接口易用,只需要少量的代碼就可以實(shí)現(xiàn)復(fù)雜的動(dòng)畫(huà)效果
- 運(yùn)行在后臺(tái)線程中,在動(dòng)畫(huà)過(guò)程中響應(yīng)交互事件(UIView動(dòng)畫(huà)
默認(rèn)動(dòng)畫(huà)過(guò)程中不響應(yīng)交互事件)
四、CATransaction的使用
CATransaction
顧名思義“事務(wù)”,創(chuàng)建動(dòng)畫(huà)事務(wù)的目的是為了操作的原子性,它的目的就是能保證多個(gè)“動(dòng)畫(huà)屬性”的同時(shí)生效。它也分為隱式和顯式,在RunLoop
中修改“動(dòng)畫(huà)屬性”,如果當(dāng)前沒(méi)有創(chuàng)建CATransaction
,系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)CATransaction
,并在當(dāng)前線程的下一個(gè)RunLoop
中commit
這個(gè)CATransaction
,這種動(dòng)畫(huà)方式稱為隱式動(dòng)畫(huà)。使用CATransaction
類中的[CATransaction begin]
和[CATransaction commit]
等相關(guān)方法創(chuàng)建的動(dòng)畫(huà)稱為顯式動(dòng)畫(huà)。顯式事務(wù)中可以定義事務(wù)中所有動(dòng)畫(huà)的運(yùn)行時(shí)間和時(shí)間函數(shù),此外,還有這個(gè)方法+ (void)setDisableActions:(BOOL)flag
能顯式的關(guān)閉這個(gè)事務(wù)中的action
查詢操作,關(guān)閉了查詢也就是關(guān)閉了動(dòng)畫(huà)效果,屬性值的變化就會(huì)立即生效,而沒(méi)有動(dòng)畫(huà)效果了。
關(guān)聯(lián)引申??????????
隱式動(dòng)畫(huà)的原理是:當(dāng)我們直接對(duì)可動(dòng)畫(huà)屬性賦值的時(shí)候,由于有隱式動(dòng)畫(huà)存在的可能,CALayer
首先會(huì)判斷此時(shí)有沒(méi)有隱式動(dòng)畫(huà)被觸發(fā)。它會(huì)讓它的delegate
(沒(méi)錯(cuò)CALayer
擁有一個(gè)屬性叫做delegate
)調(diào)用actionForLayer:forKey:
來(lái)獲取一個(gè)返回值,這個(gè)返回值在聲明的時(shí)候是一個(gè)id
對(duì)象,當(dāng)然在運(yùn)行時(shí)它可能是任何對(duì)象。這時(shí)CALayer
拿到返回值,將進(jìn)行判斷:如果返回的對(duì)象是一個(gè)nil
,則進(jìn)行默認(rèn)的隱式動(dòng)畫(huà);如果返回的對(duì)象是一個(gè)[NSNull null]
,則CALayer
不會(huì)做任何動(dòng)畫(huà);如果是一個(gè)正確的實(shí)現(xiàn)了CAAction
協(xié)議的對(duì)象,則CALayer
用這個(gè)對(duì)象來(lái)生成一個(gè)CAAnimation
,并加到自己身上進(jìn)行動(dòng)畫(huà)。
以重寫(xiě)的CALayer的position屬性的setter方法作例子:
- (void)setPosition:(CGPoint)position
{
if ([self.delegate respondsToSelector:@selector(actionForLayer:forKey:)]) {
id obj = [self.delegate actionForLayer:self forKey:@"position"];
if (!obj) {
// 隱式動(dòng)畫(huà)
} else if ([obj isKindOfClass:[NSNull class]]) {
// 直接重繪(無(wú)動(dòng)畫(huà))
} else {
// 使用obj生成CAAnimation
CAAnimation * animation;
[self addAnimation:animation forKey:nil];
}
}
}
CATransaction
屬性介紹:
//在當(dāng)前線程開(kāi)啟一個(gè)新的事務(wù)
+ (void)begin;
//提交當(dāng)前事務(wù)期間所做的全部修改,如果不存在事務(wù)則會(huì)引發(fā)異常
+ (void)commit;
//提交一個(gè)現(xiàn)存的隱士事務(wù),將推遲提交知道實(shí)際提交嵌套的顯示事務(wù)已經(jīng)完成
+ (void)flush;
//加鎖,保證線程安全
+ (void)lock;
+ (void)unlock;
//獲取和設(shè)定事務(wù)持續(xù)時(shí)間,默認(rèn)為:0.25
+ (CFTimeInterval)animationDuration;
+ (void)setAnimationDuration:(CFTimeInterval)dur;
//暫時(shí)禁用圖層的行為
+ (BOOL)disableActions;
+ (void)setDisableActions:(BOOL)flag;
CATransaction
動(dòng)畫(huà)的基本寫(xiě)法及示例代碼:
[CATransaction begin];
[CATransaction setDisableActions:YES]; //關(guān)閉動(dòng)畫(huà)
[CATransaction setValue:@(0.5f) forKey:kCATransactionAnimationDuration]; //動(dòng)畫(huà)時(shí)間
animationLayer.position = CGPointMake(100, 100);
[CATransaction commit];
注意:事務(wù)還支持嵌套,當(dāng)嵌套的時(shí)候,只有最外層的事務(wù)commit
了之后,整個(gè)動(dòng)畫(huà)才會(huì)開(kāi)始。
五、UIImageView的動(dòng)畫(huà)
UIImageView
的動(dòng)畫(huà)是可以讓一系列的圖片在特定的時(shí)間內(nèi)按照順序顯示。
UIImageView
類中有關(guān)動(dòng)畫(huà)的屬性和方法介紹:
//動(dòng)畫(huà)普通狀態(tài)下的圖片數(shù)組
@property (nullable, nonatomic, copy) NSArray<UIImage *> *animationImages;
//動(dòng)畫(huà)高亮狀態(tài)下的圖片數(shù)組
@property (nullable, nonatomic, copy) NSArray<UIImage *> *highlightedAnimationImages;
//動(dòng)畫(huà)持續(xù)時(shí)間
@property (nonatomic) NSTimeInterval animationDuration;
//動(dòng)畫(huà)重復(fù)次數(shù)
@property (nonatomic) NSInteger animationRepeatCount;
- (void)startAnimating; //開(kāi)始動(dòng)畫(huà)
- (void)stopAnimating; //結(jié)束動(dòng)畫(huà)
- (BOOL)isAnimating; //是否在動(dòng)畫(huà)中
UIImageView
的使用方法很簡(jiǎn)單按照要求傳值即可,示例代碼:
NSArray *imagesArray = @[[UIImage imageNamed:@"image1.png"],
[UIImage imageNamed:@"image2.png"],
[UIImage imageNamed:@"image3.png"]];
UIImageView *imageView = [UIImageView alloc] init];
[imageView setFrame:CGRectMake(0, 0, 100, 100)];
imageView.animationImages = imagesArray; //將序列幀數(shù)組賦給animationImages屬性
imageView.animationDuration = 0.25; //設(shè)置動(dòng)畫(huà)時(shí)間
imageView.animationRepeatCount = 0; //設(shè)置動(dòng)畫(huà)次數(shù) 0 表示無(wú)限
[self.view addSubview:imageView];
[imageView startAnimating]; //開(kāi)始播放動(dòng)畫(huà)
值得注意的地方是:圖片較少的情況,這種方法最簡(jiǎn)單實(shí)用;但如果圖片很多的話,這種方式可能會(huì)導(dǎo)致程序出現(xiàn)問(wèn)題。
UIImageView
動(dòng)畫(huà)的其他缺陷是:動(dòng)畫(huà)不能夠?qū)崿F(xiàn)暫停只能停止。如有暫停的需求時(shí),用animationImages
這種方式實(shí)現(xiàn)已經(jīng)不太滿足要求。我們可以使用NSTimer
去實(shí)現(xiàn)UIImageView
的animation
的效果,用NSTimer
每隔一個(gè)時(shí)間戳去設(shè)置一次image
,具體代碼如下:
//創(chuàng)建定時(shí)器定時(shí)更新圖片內(nèi)容
NSTimer *animatedTimer = [NSTimer scheduledTimerWithTimeInterval:0.04
target:self
selector:@selector(updateImageViewContentMethod)
userInfo:nil
repeats:YES];
//在定時(shí)器方法中更新圖片內(nèi)容
- (void)updateImageViewContentMethod
{
animatedView.image = [UIImage imageNamed:[NSStringstringWithFormat:@"image%i.png",index]];
}
六、UIActivityIndicatorView的動(dòng)畫(huà)
UIActivityIndicatorView
的是一個(gè)可以旋轉(zhuǎn)的進(jìn)度輪,一般用來(lái)當(dāng)loading
使用。
UIActivityIndicatorView
的類介紹:
//進(jìn)度輪的風(fēng)格
@property(nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
//當(dāng)動(dòng)畫(huà)停止時(shí)是否隱藏進(jìn)度輪
@property(nonatomic) BOOL hidesWhenStopped;
//iOS5后添加的設(shè)置進(jìn)度輪顏色的屬性
@property (nullable, readwrite, nonatomic, strong) UIColor *color;
//初始化方法
- (id)initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyle)style;
- (id)initWithFrame:(CGRect)frame;
//開(kāi)始旋轉(zhuǎn)
- (void)startAnimating;
//結(jié)束旋轉(zhuǎn)
- (void)stopAnimating;
//是否正在旋轉(zhuǎn)
- (BOOL)isAnimating;
UIActivityIndicatorView
的初始化方法一般使用initWithActivityIndicatorStyle
方法,UIActivityIndicatorViewStyle
有三個(gè)枚舉值可供選擇:
enum {
UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器
UIActivityIndicatorViewStyleWhite //標(biāo)準(zhǔn)尺寸白色指示器
UIActivityIndicatorViewStyleGray //灰色指示器,用于白色背景
};
基本使用方法及示例代碼:
UIActivityIndicatorView *animationView = nil;
animationView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
animationView.center = self.view.center;
[animationView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
[animationView setBackgroundColor:[UIColor lightGrayColor]];
[self.view addSubview:animationView];
[animationView startAnimating];
關(guān)聯(lián)引申??????????
關(guān)于另一種旋轉(zhuǎn)輪:經(jīng)常在網(wǎng)絡(luò)請(qǐng)求時(shí)狀態(tài)欄上也出現(xiàn)旋轉(zhuǎn)輪,這個(gè)是怎么添加的。具體代碼:
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];