什么是隱式動畫?
首先為 view 的根 layer 添加一個 subLayer
CALayer *testLayer = [CALayer layer];
testLayer.frame = CGRectMake(50, 50, 100, 100);
testLayer.backgroundColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:testLayer];
self.testLayer = testLayer;
然后嘗試修改它的顏色
self.testLayer.backgroundColor = [UIColor blueColor].CGColor;
當(dāng)改變了 CALayer 的一個可做動畫的屬性
它并不是立刻在屏幕上體現(xiàn)出來
它是從先前的值平滑過渡到新的值(從紅色漸變到了藍(lán)色)
這一切都是默認(rèn)的行為,我們不需要做額外的操作。
這其實(shí)就是隱式動畫
之所以叫隱式是因?yàn)槲覀儾]有指定任何動畫的類型
我們僅僅改變了一個屬性
然后 Core Animation 來決定如何并且何時去做動畫
當(dāng)然 Core Animaiton 同樣支持顯式動畫
但當(dāng)改變一個屬性 Core Animation 是如何判斷動畫類型和持續(xù)時間的呢?
實(shí)際上動畫執(zhí)行的時間取決于當(dāng)前事務(wù)的設(shè)置,動畫類型取決于圖層行為
事務(wù) 實(shí)際上是 Core Animation 用來包含一系列屬性動畫集合的機(jī)制
任何用指定事務(wù)去改變可以做動畫的圖層屬性都不會立刻發(fā)生變化
而是當(dāng)事務(wù)一旦提交的時候開始用一個動畫過渡到新值
事務(wù)是通過 CATransaction 類來做管理
這個類的設(shè)計有些奇怪
不像你從它的命名預(yù)期的那樣去管理一個簡單的事務(wù)
而是管理了一疊你不能訪問的事務(wù)
CATransaction 沒有屬性或者實(shí)例方法
并且也不能用 +alloc 和 -init 方法創(chuàng)建它
但是可以用 +begin 和 +commit 分別來入?;蛘叱鰲?。
任何可以做動畫的圖層屬性都會被添加到棧頂?shù)?code>事務(wù)
你可以通過 +setAnimationDuration: 方法設(shè)置當(dāng)前事務(wù)的動畫時間
或者通過 +animationDuration 方法來獲取值(默認(rèn)0.25秒)。
Core Animation 在每個 run loop 周期中自動開始一次新的事務(wù)
即使你不顯式的用 [CATransaction begin] 開始一次事務(wù)
任何在一次 run loop 循環(huán)中屬性的改變都會被集中起來
然后做一次0.25秒的動畫
修改隱式動畫
于是我么可以嘗試使用Core Animation來修改動畫的屬性
我們可以用當(dāng)前事務(wù)的+setAnimationDuration:方法來修改動畫時間
但在這里我們首先起一個新的事務(wù)
于是修改時間就不會有別的副作用
因?yàn)樾薷漠?dāng)前事務(wù)的時間可能會導(dǎo)致同一時刻別的動畫(如屏幕旋轉(zhuǎn))
所以最好還是在調(diào)整動畫之前壓入一個新的事務(wù)
- (IBAction)changeColor
{
//begin a new transaction
[CATransaction begin];
//set the animation duration to 1 second
[CATransaction setAnimationDuration:1.0];
//randomize the layer background color
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.testLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
//commit the transaction
[CATransaction commit];
}
UIView 有兩個方法
+beginAnimations:context:和+commitAnimations
這與
CATransaction的+begin和+commit方法類似
實(shí)際上在+beginAnimations:context:和+commitAnimations之間所有視圖或者圖層屬性的改變而做的動畫都是由于設(shè)置了CATransaction的原因
在iOS4中,蘋果對 UIView 添加了一種基于 block 的動畫方法:+animateWithDuration:animations:
這樣寫對做一堆的屬性動畫在語法上會更加簡單
但實(shí)質(zhì)上它們都是在做同樣的事情
CATransaction的+begin和+commit方法在+animateWithDuration:animations:內(nèi)部自動調(diào)用
這樣block中所有屬性的改變都會被事務(wù)所包含
這樣也可以避免開發(fā)者由于對+begin和+commit匹配的失誤造成的風(fēng)險
完成塊
基于 UIView 的 block 的動畫允許你在動畫結(jié)束的時候提供一個完成的動作
CATranscation 接口提供的 +setCompletionBlock: 方法也有同樣的功能
- (IBAction)changeColor
{
//begin a new transaction
[CATransaction begin];
//set the animation duration to 1 second
[CATransaction setAnimationDuration:1.0];
//add the spin animation on completion
[CATransaction setCompletionBlock:^{
//rotate the layer 90 degrees
CGAffineTransform transform = self.colorLayer.affineTransform;
transform = CGAffineTransformRotate(transform, M_PI_2);
self. testLayer.affineTransform = transform;
}];
//randomize the layer background color
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self. testLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
//commit the transaction
[CATransaction commit];
}
注意旋轉(zhuǎn)動畫要比顏色漸變快得多
這是因?yàn)橥瓿蓧K是在顏色漸變的事務(wù)提交并出棧之后才被執(zhí)行
于是,用默認(rèn)的事務(wù)做變換,默認(rèn)的時間也就變成了0.25秒
另一篇討論 View 的根 layer 為什么沒有動畫