国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

7.3 圖層行為

2018-02-24 15:07 更新

圖層行為

現(xiàn)在來做個實驗,試著直接對UIView關聯(lián)的圖層做動畫而不是一個單獨的圖層。清單7.4是對清單7.2代碼的一點修改,移除了colorLayer,并且直接設置layerView關聯(lián)圖層的背景色。

清單7.4 直接設置圖層的屬性

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //set the color of our layerView backing layer directly
    self.layerView.layer.backgroundColor = [UIColor blueColor].CGColor;
}

- (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.layerView.layer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
    //commit the transaction
    [CATransaction commit];
}

運行程序,你會發(fā)現(xiàn)當按下按鈕,圖層顏色瞬間切換到新的值,而不是之前平滑過渡的動畫。發(fā)生了什么呢?隱式動畫好像被UIView關聯(lián)圖層給禁用了。

試想一下,如果UIView的屬性都有動畫特性的話,那么無論在什么時候修改它,我們都應該能注意到的。所以,如果說UIKit建立在Core Animation(默認對所有東西都做動畫)之上,那么隱式動畫是如何被UIKit禁用掉呢?

我們知道Core Animation通常對CALayer的所有屬性(可動畫的屬性)做動畫,但是UIView把它關聯(lián)的圖層的這個特性關閉了。為了更好說明這一點,我們需要知道隱式動畫是如何實現(xiàn)的。

我們把改變屬性時CALayer自動應用的動畫稱作行為,當CALayer的屬性被修改時候,它會調(diào)用-actionForKey:方法,傳遞屬性的名稱。剩下的操作都在CALayer的頭文件中有詳細的說明,實質上是如下幾步:

  • 圖層首先檢測它是否有委托,并且是否實現(xiàn)CALayerDelegate協(xié)議指定的-actionForLayer:forKey方法。如果有,直接調(diào)用并返回結果。
  • 如果沒有委托,或者委托沒有實現(xiàn)-actionForLayer:forKey方法,圖層接著檢查包含屬性名稱對應行為映射的actions字典。
  • 如果actions字典沒有包含對應的屬性,那么圖層接著在它的style字典接著搜索屬性名。
  • 最后,如果在style里面也找不到對應的行為,那么圖層將會直接調(diào)用定義了每個屬性的標準行為的-defaultActionForKey:方法。

所以一輪完整的搜索結束之后,-actionForKey:要么返回空(這種情況下將不會有動畫發(fā)生),要么是CAAction協(xié)議對應的對象,最后CALayer拿這個結果去對先前和當前的值做動畫。

于是這就解釋了UIKit是如何禁用隱式動畫的:每個UIView對它關聯(lián)的圖層都扮演了一個委托,并且提供了-actionForLayer:forKey的實現(xiàn)方法。當不在一個動畫塊的實現(xiàn)中,UIView對所有圖層行為返回nil,但是在動畫block范圍之內(nèi),它就返回了一個非空值。我們可以用一個demo做個簡單的實驗(清單7.5)

清單7.5 測試UIView的actionForLayer:forKey:實現(xiàn)

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //test layer action when outside of animation block
    NSLog(@"Outside: %@", [self.layerView actionForLayer:self.layerView.layer forKey:@"backgroundColor"]);
    //begin animation block
    [UIView beginAnimations:nil context:nil];
    //test layer action when inside of animation block
    NSLog(@"Inside: %@", [self.layerView actionForLayer:self.layerView.layer forKey:@"backgroundColor"]);
    //end animation block
    [UIView commitAnimations];
}

@end

運行程序,控制臺顯示結果如下:

$ LayerTest[21215:c07] Outside: <null>
$ LayerTest[21215:c07] Inside: <CABasicAnimation: 0x757f090>

于是我們可以預言,當屬性在動畫塊之外發(fā)生改變,UIView直接通過返回nil來禁用隱式動畫。但如果在動畫塊范圍之內(nèi),根據(jù)動畫具體類型返回相應的屬性,在這個例子就是CABasicAnimation(第八章“顯式動畫”將會提到)。

當然返回nil并不是禁用隱式動畫唯一的辦法,CATransacition有個方法叫做+setDisableActions:,可以用來對所有屬性打開或者關閉隱式動畫。如果在清單7.2的[CATransaction begin]之后添加下面的代碼,同樣也會阻止動畫的發(fā)生:

[CATransaction setDisableActions:YES];

總結一下,我們知道了如下幾點

  • UIView關聯(lián)的圖層禁用了隱式動畫,對這種圖層做動畫的唯一辦法就是使用UIView的動畫函數(shù)(而不是依賴CATransaction),或者繼承UIView,并覆蓋-actionForLayer:forKey:方法,或者直接創(chuàng)建一個顯式動畫(具體細節(jié)見第八章)。
  • 對于單獨存在的圖層,我們可以通過實現(xiàn)圖層的-actionForLayer:forKey:委托方法,或者提供一個actions字典來控制隱式動畫。

我們來對顏色漸變的例子使用一個不同的行為,通過給colorLayer設置一個自定義的actions字典。我們也可以使用委托來實現(xiàn),但是actions字典可以寫更少的代碼。那么到底改如何創(chuàng)建一個合適的行為對象呢?

行為通常是一個被Core Animation隱式調(diào)用的顯式動畫對象。這里我們使用的是一個實現(xiàn)了CATransaction的實例,叫做推進過渡。

第八章中將會詳細解釋過渡,不過對于現(xiàn)在,知道CATransition響應CAAction協(xié)議,并且可以當做一個圖層行為就足夠了。結果很贊,不論在什么時候改變背景顏色,新的色塊都是從左側滑入,而不是默認的漸變效果。

清單7.6 實現(xiàn)自定義行為

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;
@property (nonatomic, weak) IBOutlet CALayer *colorLayer;/*熱心人發(fā)現(xiàn)這里應該改為@property (nonatomic, strong)  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 a custom action
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromLeft;
    self.colorLayer.actions = @{@"backgroundColor": transition};
    //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

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號