[iOS Animation]-CALayer 隱式動畫

隱式動畫

按照個人意思去作,而不是我說的。 -- 埃德娜,辛普森 git

咱們在第一部分討論了Core Animation除了動畫以外能夠作到的任何事情。可是動畫是Core Animation庫一個很是顯著的特性。這一章咱們來看看它是怎麼作到的。具體來講,咱們先來討論框架自動完成的隱式動畫(除非你明確禁用了這個功能)。 github

事務

Core Animation基於一個假設,說屏幕上的任何東西均可以(或者可能)作動畫。動畫並不須要你在Core Animation中手動打開,相反須要明確地關閉,不然他會一直存在。 網絡

當你改變 CALayer 的一個可作動畫的屬性,它並不能馬上在屏幕上體現出來。相反,它是從先前的值平滑過渡到新的值。這一切都是默認的行爲,你不須要作額外的操做。 框架

這看起來這太棒了,彷佛不太真實,咱們來用一個demo解釋一下:首先和第一章「圖層樹」同樣建立一個藍色的方塊,而後添加一個按鈕,隨機改變它的顏色。代碼見清單7.1。點擊按鈕,你會發現圖層的顏色平滑過渡到一個新值,而不是跳變(圖7.1)。 dom

清單7.1 隨機改變圖層顏色 oop

複製代碼
@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 green:green blue:blue alpha:1.0].CGColor;  } @end
複製代碼

 

圖7.1

圖7.1 添加一個按鈕來控制圖層顏色 動畫

這其實就是所謂的隱式動畫。之因此叫隱式是由於咱們並無指定任何動畫的類型。咱們僅僅改變了一個屬性,而後Core Animation來決定如何而且什麼時候去作動畫。Core Animaiton一樣支持顯式動畫,下章詳細說明。 atom

但當你改變一個屬性,Core Animation是如何判斷動畫類型和持續時間的呢?實際上動畫執行的時間取決於當前事務的設置,動畫類型取決於圖層行爲spa

事務其實是Core Animation用來包含一系列屬性動畫集合的機制,任何用指定事務去改變能夠作動畫的圖層屬性都不會馬上發生變化,而是當事務一旦提交的時候開始用一個動畫過渡到新值。 設計

事務是經過 CATransaction 類來作管理,這個類的設計有些奇怪,不像你從它的命名預期的那樣去管理一個簡單的事務,而是管理了一疊你不能訪問的事務。CATransaction沒有屬性或者實例方法,而且也不能用+alloc和-init方法建立它。可是能夠用 +begin 和 +commit 分別來入棧或者出棧。

任何能夠作動畫的圖層屬性都會被添加到棧頂的事務,你能夠經過 +setAnimationDuration: 方法設置當前事務的動畫時間,或者經過 +animationDuration 方法來獲取值(默認0.25秒)。

Core Animation在每一個run loop週期中自動開始一次新的事務(run loop是iOS負責收集用戶輸入,處理定時器或者網絡事件而且從新繪製屏幕的東西),即便你不顯式的用[CATransaction begin]開始一次事務,任何在一次run loop循環中屬性的改變都會被集中起來,而後作一次0.25秒的動畫。

明白這些以後,咱們就能夠輕鬆修改變色動畫的時間了。咱們固然能夠用當前事務的+setAnimationDuration:方法來修改動畫時間,但在這裏咱們首先起一個新的事務,因而修改時間就不會有別的反作用。由於修改當前事務的時間可能會致使同一時刻別的動畫(如屏幕旋轉),因此最好仍是在調整動畫以前壓入一個新的事務。

修改後的代碼見清單7.2。運行程序,你會發現色塊顏色比以前變得更慢了。

清單7.2 使用CATransaction控制動畫時間

複製代碼
- (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 green:green blue:blue alpha:1.0].CGColor; //commit the transaction  [CATransaction commit]; }
複製代碼

 

若是你用過UIView的動畫方法作過一些動畫效果,那麼應該對這個模式不陌生。UIView有兩個方法,+beginAnimations:context:和+commitAnimations,和CATransaction的+begin和+commit方法相似。實際上在 +beginAnimations:context: 和 +commitAnimations 之間全部視圖或者圖層屬性的改變而作的動畫都是因爲設置了CATransaction的緣由。

在iOS4中,蘋果對UIView添加了一種基於block的動畫方法: +animateWithDuration:animations: 。這樣寫對作一堆的屬性動畫在語法上會更加簡單,但實質上它們都是在作一樣的事情。

CATransaction的+begin和+commit方法在+animateWithDuration:animations:內部自動調用,這樣block中全部屬性的改變都會被事務所包含。這樣也能夠避免開發者因爲對+begin和+commit匹配的失誤形成的風險。

相關文章
相關標籤/搜索