關(guān)于隱式動(dòng)畫(huà)

最近看了點(diǎn)動(dòng)畫(huà)方面的知識(shí),做個(gè)筆記記錄一下。

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *contentView;
@property (nonatomic,strong) CALayer *colorlayer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.colorlayer = [CALayer layer];
    self.colorlayer.frame = CGRectMake(0, 0, 100, 100);
    self.colorlayer.backgroundColor = [UIColor redColor].CGColor;
    [self.contentView.layer addSublayer:self.colorlayer];
    
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    CGFloat red = arc4random_uniform(256) / 255.0;
    CGFloat gre = arc4random_uniform(256) / 255.0;
    CGFloat blu = arc4random_uniform(256) / 255.0;
    self.colorlayer.backgroundColor = [UIColor colorWithRed:red green:gre blue:blu alpha:1.0].CGColor;
    
}

這就是隱式動(dòng)畫(huà),僅僅改變了Layer的backgroundColor屬性,運(yùn)行卻有動(dòng)畫(huà)效果。

實(shí)際上動(dòng)畫(huà)執(zhí)行的時(shí)間取決于當(dāng)前事務(wù)的設(shè)置,動(dòng)畫(huà)類(lèi)型取決于圖層行為。

事務(wù)是通過(guò)CATransaction類(lèi)來(lái)做管理,CATransaction沒(méi)有屬性或者實(shí)例方法,并且也不能用+alloc和-init方法創(chuàng)建它。但是可以用+begin和+commit分別來(lái)入?;蛘叱鰲?。任何可以做動(dòng)畫(huà)的圖層屬性都會(huì)被添加到棧頂?shù)氖聞?wù),你可以通過(guò)+setAnimationDuration:方法設(shè)置當(dāng)前事務(wù)的動(dòng)畫(huà)時(shí)間,或者通過(guò)+animationDuration方法來(lái)獲取值(默認(rèn)0.25秒)。

Core Animation在每個(gè)run loop周期中自動(dòng)開(kāi)始一次新的事務(wù)(run loop是iOS負(fù)責(zé)收集用戶輸入,處理定時(shí)器或者網(wǎng)絡(luò)事件并且重新繪制屏幕的東西),即使你不顯式的用[CATransaction begin]開(kāi)始一次事務(wù),任何在一次run loop循環(huán)中屬性的改變都會(huì)被集中起來(lái),然后做一次0.25秒的動(dòng)畫(huà)。

所以事務(wù)是通過(guò)CATransaction類(lèi)隱式得設(shè)置了動(dòng)畫(huà)執(zhí)行時(shí)間,我們也可以通過(guò)setAnimationDuration設(shè)置動(dòng)畫(huà)時(shí)間。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    // 如果我們要自己通過(guò)setAnimationDuration設(shè)置動(dòng)畫(huà)執(zhí)行時(shí)間,必須要先起一個(gè)新的事務(wù),因?yàn)樾薷漠?dāng)前事務(wù)的時(shí)間可能會(huì)導(dǎo)致同一時(shí)刻別的動(dòng)畫(huà),所以最好是在調(diào)整動(dòng)畫(huà)之前壓入一個(gè)新的事務(wù)。
    [CATransaction begin];
    
    // 默認(rèn)為0.25秒
    [CATransaction setAnimationDuration:0.25];
    
    CGFloat red = arc4random_uniform(256) / 255.0;
    CGFloat gre = arc4random_uniform(256) / 255.0;
    CGFloat blu = arc4random_uniform(256) / 255.0;
    self.colorlayer.backgroundColor = [UIColor colorWithRed:red green:gre blue:blu alpha:1.0].CGColor;
    
    [CATransaction commit];
    
}
UIView有兩個(gè)方法,+beginAnimations:context:和+commitAnimations、+animateWithDuration:animations:,和CATransaction的+begin和+commit方法類(lèi)似。實(shí)際上在+beginAnimations:context:和+commitAnimations之間所有視圖或者圖層屬性的改變而做的動(dòng)畫(huà)都是由于設(shè)置了CATransaction的原因。

UIView的+animateWithDuration:animations:提供了一個(gè)block允許在動(dòng)畫(huà)結(jié)束后做一些操作,CATransaction也提供了一個(gè)+setCompletionBlock:方法。

關(guān)于隱式動(dòng)畫(huà),還有最重要的一點(diǎn)是:rootLayer不執(zhí)行隱式動(dòng)畫(huà)。
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.contentView.layer.backgroundColor = [UIColor redColor].CGColor;

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    CGFloat red = arc4random_uniform(256) / 255.0;
    CGFloat gre = arc4random_uniform(256) / 255.0;
    CGFloat blu = arc4random_uniform(256) / 255.0;
    self.contentView.layer.backgroundColor = [UIColor colorWithRed:red green:gre blue:blu alpha:1.0].CGColor;
    
}

點(diǎn)擊屏幕,圖層顏色是瞬間切換的,沒(méi)有了動(dòng)畫(huà)效果。我們知道動(dòng)畫(huà)類(lèi)型取決于圖層行為,圖層行為是
我們把改變屬性時(shí)CALayer自動(dòng)應(yīng)用的動(dòng)畫(huà)稱作行為,當(dāng)CALayer的屬性被修改時(shí)候,它會(huì)調(diào)用-actionForKey:方法,傳遞屬性的名稱。剩下的操作都在CALayer的頭文件中有詳細(xì)的說(shuō)明,實(shí)質(zhì)上是如下幾步:

  • 圖層首先檢測(cè)它是否有委托,并且是否實(shí)現(xiàn)CALayerDelegate協(xié)議指定的-actionForLayer:forKey方法。如果有,直接調(diào)用并返回結(jié)果。
  • 如果沒(méi)有委托,或者委托沒(méi)有實(shí)現(xiàn)-actionForLayer:forKey方法,圖層接著檢查包含屬性名稱對(duì)應(yīng)行為映射的actions字典。
  • 如果actions字典沒(méi)有包含對(duì)應(yīng)的屬性,那么圖層接著在它的style字典接著搜索屬性名。
  • 最后,如果在style里面也找不到對(duì)應(yīng)的行為,那么圖層將會(huì)直接調(diào)用定義了每個(gè)屬性的標(biāo)準(zhǔn)行為的-defaultActionForKey:方法。
    所以一輪完整的搜索結(jié)束之后,-actionForKey:要么返回空(這種情況下將不會(huì)有動(dòng)畫(huà)發(fā)生),要么是CAAction協(xié)議對(duì)應(yīng)的對(duì)象,最后CALayer拿這個(gè)結(jié)果去對(duì)先前和當(dāng)前的值做動(dòng)畫(huà)。

于是這就解釋了UIKit是如何禁用隱式動(dòng)畫(huà)的:每個(gè)UIView對(duì)它關(guān)聯(lián)的圖層都扮演了一個(gè)委托,并且提供了-actionForLayer:forKey的實(shí)現(xiàn)方法。當(dāng)不在一個(gè)動(dòng)畫(huà)塊的實(shí)現(xiàn)中,UIView對(duì)所有圖層行為返回nil,但是在動(dòng)畫(huà)block范圍之內(nèi),它就返回了一個(gè)非空值。
我們可以測(cè)試一下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.contentView.layer.backgroundColor = [UIColor redColor].CGColor;

    NSLog(@"1 --- %@",[self.contentView actionForLayer:self.contentView.layer forKey:@"backgroundColor"]);
    
    [UIView beginAnimations:nil context:nil];
    
    NSLog(@"2 --- %@",[self.contentView actionForLayer:self.contentView.layer forKey:@"backgroundColor"]);
    
    [UIView commitAnimations];
}
2017-04-11 11:05:22.758 隱式動(dòng)畫(huà)[3583:3064040] 1 --- <null>
2017-04-11 11:05:22.759 隱式動(dòng)畫(huà)[3583:3064040] 2 --- <CABasicAnimation: 0x61000003da00>```

所以-actionForKey:返回nil,這種情況下就不執(zhí)行動(dòng)畫(huà)。我們也可以通過(guò)[CATransaction setDisableActions:YES];阻止動(dòng)畫(huà)執(zhí)行。

行為通常是一個(gè)被Core Animation隱式調(diào)用的顯式動(dòng)畫(huà)對(duì)象。
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
self.colorLayer.actions = @{@"backgroundColor": transition};

[self.contentView.layer addSublayer:self.colorlayer];   

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

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

  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫(huà)全貌。在這里你可以看...
    F麥子閱讀 5,273評(píng)論 5 13
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫(huà)全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,698評(píng)論 6 30
  • 在前面的學(xué)習(xí)中,我們討論了CoreAnimation除了動(dòng)畫(huà)外可以做到的任何事情。但是動(dòng)畫(huà)是CoreAni...
    小貓仔閱讀 1,629評(píng)論 0 0
  • 前言 本文只要描述了iOS中的Core Animation(核心動(dòng)畫(huà):隱式動(dòng)畫(huà)、顯示動(dòng)畫(huà))、貝塞爾曲線、UIVie...
    GitHubPorter閱讀 3,750評(píng)論 7 11
  • 隱式動(dòng)畫(huà) 按照我的意思去做,而不是我說(shuō)的。 -- 埃德娜,辛普森 我們?cè)诘谝徊糠钟懻摿顺藙?dòng)畫(huà)之外,Core An...
    方圓幾度閱讀 133評(píng)論 0 0

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