關(guān)于隱式動畫的一些筆記

什么是隱式動畫?

首先為 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 為什么沒有動畫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容