Do What I mean, not what I say
Implicit Animations
首先看一個demo
@interface ViewController ()
@property (nonatomic, weak) IBOutlet UIView *layerView; @property (nonatomic, weak) IBOutlet CALayer *colorLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//create sublayer
self.colorLayer = [CALayer layer];
self.colorLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;
//add it to our view
[self.layerView.layer addSublayer:self.colorLayer]; }
- (IBAction)changeColor {
//randomize the layer background color
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.colorLayer.backgroundColor = [UIColor colorWithRed:red]
}
@end
在這個程序中襟士,我們并沒有看到任何代碼和動畫相關(guān)蜕青。我們只是單純的更改了一個非UIView關(guān)聯(lián)的Layer的屬性(一定要是非UIView相關(guān)聯(lián)的Layer,后文會解釋原因)。當(dāng)我們改變一個屬性時怀薛,Core Animation是怎么判斷動畫類型和持續(xù)時間呢?實際上動畫執(zhí)行的時間取決于當(dāng)前事務(wù)(Transaction)的設(shè)置,動畫類型取決于圖層行為(Layer Action)傍药。事務(wù)實際上是Core Animation用來包含一系列動畫集合的機(jī)制,任何時候在一個指定事務(wù)中去改變都不會立刻發(fā)生變化,而是當(dāng)事務(wù)提交的時候開始用一個動畫過渡到新值拐辽。事務(wù)是通過CATransation 類來管理的拣挪,這個類的設(shè)計很有意思,不像它的名字俱诸,它管理了一個你不能直接訪問的事務(wù)的棧菠劝。CATransaction沒有屬性或者實例方法,并且也不能使用alloc睁搭,init來創(chuàng)建赶诊。然而,你可以通過類方法园骆,+begin和+commit來把一個新的事務(wù)壓入棧中舔痪,或者推出當(dāng)前事件。
任何的一個可動畫的圖層的屬性的變化都會被添加到棧頂?shù)氖聞?wù)锌唾。(Any layer property change that can be animated will be added to the topmost transaction in the stack.)你可以通過+setAnimationDuration: 方法來設(shè)置當(dāng)前事務(wù)的動畫時間锄码,或者,通過+animationDuration 方法來獲取當(dāng)前的動畫時間晌涕。
Core Animation 在每一個run loop周期中自動開始一個新的事務(wù)滋捶,即是你不顯示的使用[CATransaction begin]開始一個新的事務(wù),任何一次在run loop循環(huán)中屬性的改變都會被集中起來余黎,然后坐一次0.25秒的動畫重窟。明白了這些之后,我們就可以輕松的修改變色動畫的時間了驯耻,我們當(dāng)然可以使用當(dāng)前事務(wù)的+setAnimationDuration:方法來修改動畫持續(xù)時間亲族,但是我們先起一個新的事務(wù),這樣的話修改時間就不會產(chǎn)生副作用可缚,因為修改當(dāng)前事務(wù)的時間可能會影響統(tǒng)一時刻的其他動畫霎迫,所以最好還是在調(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.colorLayer.backgroundColor = [UIColor colorWithRed:red
//commit the transaction
[CATransaction commit];
}
完成塊
基于UIView的block動畫允許你在動畫結(jié)束的時候提供一個完成塊帘靡。CATransaction接口提供的+setCompleteBlock:方法也有同樣的功能知给。
- (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.colorLayer.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.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
//commit the transaction
[CATransaction commit];
}
注意,旋轉(zhuǎn)動畫要比顏色漸變快得多描姚,這事因為完成塊是在顏色漸變得事務(wù)提交并出棧之后才被執(zhí)行涩赢,所以,用默認(rèn)的事務(wù)做變換轩勘,默認(rèn)的時間也變成了0.25秒筒扒。