编程

当前位置:永利皇宫463登录 > 编程 > 关于隐式动画,隐式动画

关于隐式动画,隐式动画

来源:http://www.makebuLuo.com 作者:永利皇宫463登录 时间:2019-09-12 14:29

这种动画被称作隐式动画。它是隐式的,因为大家从不点名大家想要爆发的动画类型;大家只是改换了质量,Core Animation决定哪些以及哪一天去动画改换它。Core Animation也提供显式卡通,那将要下一章中等教育授。

#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;

}

小说摘录自:https://github.com/AttackOnDobby/iOS-Core-Animation-Advanced-Techniques

Core Animation在每个运作周期迭代中自行发轫新业务。(运行周期是iOS用来搜集客商输入、处理全部显式机械漏刻或互联网事件的,最后重新绘制荧屏。)就算你从未体现选拔[CATransaction begin]先河三遍专业,全数你在三个加以运转周期迭代中的属性别变化更都会组到一同,在0.25秒的阶段里进行动画。

关于隐式动画,还应该有最注重的少数是:rootLayer不实践隐式动画。
- (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;

}

点击荧屏,图层颜色是一念之差切换的,未有了动画效果。大家知道动画类型取决于图层行为,图层行为是
我们把退换属性时CALayer自动应用的卡通片称作行为,当CALayer的性情被修改时候,它会调用-actionForKey:方法,传递属性的名目。剩下的操作都在CALayer的头文件中有详实的验证,实质上是之类几步:

  • 图层首先检验它是还是不是有嘱托,何况是不是落到实处CALayerDelegate左券钦定的-actionForLayer:forKey方法。即便有,直接调用并重临结果。
  • 只要未有嘱托,或然委托未有兑现-actionForLayer:forKey方法,图层接着检查满含属性名称对应行为映射的actions字典。
  • 借使actions字典未有包涵相应的习性,那么图层接着在它的style字典接着搜索属性名。
  • 末尾,若是在style里面也找不到相应的行为,那么图层将会直接调用定义了每一个属性的正式作为的-defaultActionForKey:方法。
    据此一轮完整的搜寻甘休之后,-actionForKey:要么再次来到空(这种景观下将不会有动画发生),要么是CAAction左券对应的对象,最终CALayer拿那一个结果去对在此之前和眼下的值做动画。

于是乎那就解释了UI基特是何许禁止使用隐式动画的:种种UIView对它事关的图层都扮演了三个寄托,况且提供了-actionForLayer:forKey的贯彻形式。当不在一个卡通块的落实中,UIView对持有图层行为重返nil,但是在动画block范围以内,它就回去了二个非空值。
大家可以测量检验一下:

- (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 隐式动画[3583:3064040] 1 --- <null>
2017-04-11 11:05:22.759 隐式动画[3583:3064040] 2 --- <CABasicAnimation: 0x61000003da00>```

所以-actionForKey:返回nil,这种情况下就不执行动画。我们也可以通过[CATransaction setDisableActions:YES];阻止动画执行。

行为通常是一个被Core Animation隐式调用的显式动画对象。

CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
self.colorLayer.actions = @{@"backgroundColor": transition};

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

需要注意的是动画效果的代码要在layer添加之前。

完成块

基于UIView的block的卡通片允许你在动画截止的时候提供一个造成的动作。CATranscation接口提供的+setCompletionBlock:艺术也许有同样的作用。大家来调度上个例子,在颜色变化结束未来推行一些操作。我们来加多三个产生之后的block,用来在历次颜色变化结束现在切换来另三个筋斗90的卡通片。代码见清单7.3,运转结果见图7.2。

清单7.3 在颜色动画完成之后增多叁个回调

- (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];
}

图片 1

图 7.2

图7.2 颜色渐变之产生现在再做一次旋转

在意旋转动画要比颜色渐变快得多,这是因为成功块是在颜色渐变的事情提交并出栈之后才被试行,于是,用暗中同意的政工做转变,私下认可的小时也就改成了0.25秒。

翻译测量检验结果为:

那正是隐式动画,仅仅改动了Layer的backgroundColor属性,运维却有动画效果。

总结

这一章研讨了隐式动画,还应该有Core Animation对点名属性选用合适的动画片行为的体制。同期你精晓了UIKit是何等丰富利用Core Animation的隐式动画机制来深化它的显式系统,以及动画是什么被暗中认可禁止使用并且当要求的时候启用的。最终,你询问了表现和模型图层,以及Core Animation是什么样通过它们来剖断出图层当前地方以及将要达到的职位。

多数景况下,你无需直接待上访问体现图层;你只须要与模型图层的属性打交道,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秒的卡通片。

因而职业是由此CATransaction类隐式得设置了动画片施行时间,大家也得以经过setAnimationDuration设置动画时间。

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

    // 如果我们要自己通过setAnimationDuration设置动画执行时间,必须要先起一个新的事务,因为修改当前事务的时间可能会导致同一时刻别的动画,所以最好是在调整动画之前压入一个新的事务。
    [CATransaction begin];

    // 默认为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关联的图层做动画并不是二个独门的图层。清单7.4是对清单7.2代码的一些退换,移除了colorLayer,并且一直设置layerView波及图层的背景观。

清单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];
}

运行程序,你会发掘当按下开关,图层颜色刹那间切换成新的值,并不是前边平滑过渡的卡通片。爆发了怎么吗?隐式动画好像被UIView事关图层给禁止使用了。

试想一下,如若UIView的个性都有动画天性的话,那么不论是在如几时候修改它,大家都应有能注意到的。所以,假使说UIKit创立在Core Animation(暗许对持有东西都做动画)之上,那么隐式动画是何许被UIKit禁止使用掉呢?

咱俩精晓Core Animation日常对CALayer的装有属性(可动画的天性)做动画,不过UIView把它关系的图层的这些特点关闭了。为了更加好注脚那或多或少,大家须要掌握隐式动画是哪些落到实处的。

小编们把改换属性时CALayer电动应用的卡通称作行为,当CALayer的质量被涂改时候,它会调用-actionForKey:办法,传递属性的名目。剩下的操作都在CALayer的头文件中有详尽的证实,实质上是之类几步:

  • 图层首先检查测验它是还是不是有嘱托,並且是不是落到实处CALayerDelegate合同钦赐的-actionForLayer:forKey方法。就算有,直接调用并赶回结果。
  • 假使未有委托,或许委托未有兑现-actionForLayer:forKey方法,图层接着检查包涵属性名称对应行为映射的actions字典。
  • 如果actions字典从未包蕴相应的属性,那么图层接着在它的style字典接着搜索属性名。
  • 最后,如果在style内部也找不到相应的一颦一笑,那么图层将会间接调用定义了各样属性的正规行事的-defaultActionForKey:方法。

由此一轮完整的寻觅停止今后,-actionForKey:要么重临空(这种景观下将不会有动画爆发),要么是CAAction商业事务对应的靶子,最终CALayer拿那些结果去对原先和当前的值做动画。

于是乎那就表达了UIKit是什么禁用隐式动画的:各种UIView对它事关的图层都扮演了多少个委托,并且提供了-actionForLayer:forKey的贯彻方式。当不在二个动画片块的落到实处中,UIView对富有图层行为重回nil,不过在动画block范围以内,它就赶回了三个非空值。我们得以用三个demo做个简易的尝试(清单7.5)

清单7.5 测试UIView的actionForLayer:forKey:实现

@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>

因而跟预知的一律,当属性在动画块之外产生更换,UIView一向通过再次来到nil来剥夺隐式动画。但假使在动画块范围之内,依照动画具体品种重临相应的属性,在这么些事例正是CABasicAnimation(第八章“显式动画”将会提到)。

自然再次来到nil并非禁止使用隐式动画独一的措施,CATransaction有个艺术叫做+setDisableActions:,能够用来对持有属性张开大概关闭隐式动画。假如在清单7.2的[CATransaction begin]日后增加上面包车型大巴代码,同样也会阻止动画的发出:

[CATransaction setDisableActions:YES];

小结一下,我们精晓了如下几点

  • UIView关系的图层禁止使用了隐式动画,对这种图层做动画的独一无二形式正是运用UIView的动画函数(实际不是借助CATransaction),也许一而再UIView,并覆盖-actionForLayer:forKey:方法,也许直接开立二个显式动画(具体细节见第八章)。
  • 对于单身存在的图层,大家得以由此落到实处图层的-actionForLayer:forKey:信托方法,恐怕提供多个actions字典来支配隐式动画。

大家来对颜色渐变的事例使用三个两样的作为,通过给colorLayer安装三个自定义的actions字典修改清单7.1。大家也足以运用委托来兑现,不过actions字典能够写更加少的代码。那么到底改什么创制三个体面的一举一动指标呢?

行事平时是二个被Core Animation隐式调用的显式动画片对象。这里我们运用的是三个贯彻了CATransition的实例,叫做有利于过渡(参照他事他说加以考察清单7.6)。

第八章上校会详细分解过渡,可是对此明日,知道CATransition响应CAAction磋商,并且能够当作一个图层行为就丰盛了。结果比十分赞,不论在怎么时候改造背景颜色,新的色块都以从左边滑入,并不是暗中认可的渐变效果。(参谋图7.3)

清单7.6 实现自定义行为

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;
@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

图片 2

图7.3 使用推动过渡的色值动画

瞩目,大家的转动动画比颜色渐变动画快非常多。那是因为施加旋转的姣好闭包是有颜色渐变的作业提交后进行并出栈的。因而,会动用私下认可的业务,以及暗中认可的0.25秒时间长度。

最近看了点动画方面包车型地铁学问,做个笔记记录一下。

隐式动画

依据自个儿的意味去做,实际不是本身说的。 -- 埃德娜,辛普森

笔者们在第一有个别研商了除去动画之外,Core Animation能够完成的其余业务。不过动画是Core Animation库二个可怜引人瞩指标风味。这一章大家来探视它是怎么工作的。具体来讲,大家先来谈谈框架自动达成的隐式动画(除非你鲜明禁止使用了这一个效果)。

图片 3图7.1 增加开关来改造图层颜色

UIView有三个主意,+beginAnimations:context:和+commitAnimations、+animateWithDuration:animations:,和CATransaction的+begin和+commit方法类似。实际上在+beginAnimations:context:和+commitAnimations之间全体视图或许图层属性的更换而做的动画都以出于设置了CATransaction的由来。

UIView的+animateWithDuration:animations:提供了二个block允许在动画结束后做一些操作,CATransaction也提供了叁个+setCompletionBlock:方法。

事务

Core Animation基于八个万一,说显示屏上的别的交事务物都得以(或许恐怕)做动画。你并无需在Core Animation中手动展开动画,然而你须求分明地关闭它,不然它会一向留存。

当你退换CALayer一个可做动画的本性时,那些退换并不会马上在荧屏上反映出来。相反,该属性会从先前的值平滑过渡到新的值。这一切都以默许的一颦一笑,你没有须要做额外的操作。

这看起来那太棒了,就如不太实在,大家用八个demo来解释一下:首先和率先章“图层树”一样创设三个紫红的四方,然后增多四个按键,随机改动它的水彩。代码见清单7.1。点击按键,你会发觉图层的颜色平滑对接到一个新值,实际不是跳变(图7.1)。

清单7.1 随机更改图层颜色

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;
@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 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

图片 4

图 7.1

图7.1 增多多个开关来调控图层颜色

那实际就是所谓的隐式卡通。之所以叫隐式是因为大家并从未点名其余动画的品类。我们独有改换了贰本性质,然后Core Animation来决定哪些何况什么时候去做动画。Core Animaiton一样援助显式卡通,下章详细表达。

但当您转移叁性格质,Core Animation是怎么着决断动画类型和持续时间的呢?实际上动画试行的时间取决于当前事务的安装,动画类型取决于图层行为

事情实际上是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同盟的失误导致的高风险。

表7.2来得了修改后的代码。要是你运维应用,你会注意到颜色渐变地比原先慢多了。

突显与模型

CALayer的品质行为其实很不符合规律,因为改动贰个图层的习性并不曾及时见效,而是经过一段时间渐更换新。那是怎么达成的吗?

当您转移三个图层的品质,属性值的确是及时更新的(借使您读取它的数量,你会意识它的值在你设置它的那一刻就已经生效了),可是荧屏上并不曾立刻发生变动。那是因为你设置的品质并从未平素调解图层的外观,相反,他只是概念了图层动画甘休之后将在变化的外观。

当设置CALayer的质量,实际上是在概念当前政工甘休之后图层如何展现的模型。Core Animation扮演了一个控制器的角色,而且肩负依据图层行为和作业设置去不断更新视图的这么些属性在显示器上的景色。

大家商量的正是三个头名的微型MVC模式CALayer是三个连连客商分界面(正是MVC中的view)虚拟的类,可是在分界面自己这几个情景下,CALayer的作为更像是存款和储蓄了视图怎么着体现和动画的数据模型。实际上,在苹果本身的文书档案中,图层树日常都以值的图层树模型。

在iOS中,荧屏每分钟重绘伍十七次。假诺动画时长比60分之一秒要长,Core Animation就须要在安装一回新值和新值生效之间,对显示屏上的图层实行双重组织。这意味CALayer除开“真实”值(就是您设置的值)之外,必须要理解当前显示在显示器上的属性值的笔录。

各类图层属性的显得值都被积存在多个可以称作表现图层的独门图层其中,他能够透过-presentationLayer格局来拜候。这些展现图层实际上是模型图层的复制,可是它的属性值代表了在别的钦命期刻当前外观效果。换句话说,你能够经过呈现图层的值来取妥帖前显示器上的确展现出来的值(图7.4)。

大家在第一章中涉嫌除了图层树,别的还只怕有呈现树。展现树通过图层树中有所图层的显现图层所形成。注意表现图层仅仅当图层第一回被提交(正是第二回第三次在显示器上出示)的时候创立,所以在那在此以前调用-presentationLayer将会回去nil

您或者注意到有三个名为–modelLayer的主意。在显示图层上调用–modelLayer将会重返它正值显现所重视的CALayer。平常在三个图层上调用-modelLayer会返回–self(实际上大家早就创办的原始图层正是一种数据模型)。

图片 5

图7.4 三个运动的图层是怎么着通过数据模型展现的

大部气象下,你没有须要一向访谈显示图层,你可以通过和模型图层的相互,来让Core Animation更新展现。二种意况下表现图层会变得很有用,二个是一道动画,三个是管理顾客交互。

  • 若果你在实现三个依照沙漏的动画片(见第11章“基于停车计时器的卡通”),而不只是依靠事务的动画,那年精确地理解在某一随时图层展现在怎么职位就能够对正确摆放图层很有用了。
  • 假定你想让你做动画的图层响应客户输入,你能够行使-hitTest:主意(见第三章“图层几何学”)来剖断钦赐图层是还是不是被触摸,那时候对呈现图层实际不是模型图层调用-hitTest:会议及展览示更有意义,因为彰显图层代表了顾客眼下来看的图层地方,并不是当下动画甘休今后的岗位。

笔者们能够用叁个轻易的案例来注解前面一个(见清单7.7)。在那一个事例中,点击荧屏上的大肆个人置将会让图层平移到那边。点击图层本人能够随便改动它的水彩。大家透过对表现图层调用-hitTest:来决断是还是不是被点击。

假设改造代码让-hitTest:直接效果于colorLayer并非显现图层,你会意识当图层移动的时候它并无法准确职业。那时候你就须要点击图层将在移动到的职位并不是图层本人来响应点击(那便是用显示图层来响应hit test的来头)。

清单7.7 使用presentationLayer图层来推断当前图层地方

@interface ViewController ()

@property (nonatomic, strong) CALayer *colorLayer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //create a red layer
    self.colorLayer = [CALayer layer];
    self.colorLayer.frame = CGRectMake(0, 0, 100, 100);
    self.colorLayer.position = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
    self.colorLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.colorLayer];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //get the touch point
    CGPoint point = [[touches anyObject] locationInView:self.view];
    //check if we've tapped the moving layer
    if ([self.colorLayer.presentationLayer hitTest:point]) {
        //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;
    } else {
        //otherwise (slowly) move the layer to new position
        [CATransaction begin];
        [CATransaction setAnimationDuration:4.0];
        self.colorLayer.position = point;
        [CATransaction commit];
    }
}

@end

  • 假诺你在贯彻基于时间的卡通(见第11章“基于时间的动画”)再非平常的依照事务的卡通片,显然某临时刻点钦点图层在荧屏上的展现是特别可行的,那样您就足以在动画时不易放置任何元素。
  • 借使您想你的卡通图层响应客户输入,况且你在利用-hitTest:办法(见第3章“图层几何”)来判别钦点图层是或不是被触动了,对展示图层而非模型图层调用-hitTest:主意会更有意义,那是因为浮现图层体现了客商这段日子看见的图层地点,而非当前卡通停止后将远在的岗位。

动作一般由三个隐式动画片对象内定,它会在急需时被Core Animaiton隐式调用。这里大家用的动画是推过渡,那是由三个CATransition实例完结的。

表7.7 使用presentationLayer来判定当前图层位置import UIKitclass ViewController: UIViewController { var colorLayer: CALayer! override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 判断横屏 let screenSize = UIScreen.mainScreen().applicationFrame.size if (screenSize.width > screenSize.height) { // 创建一个红色图层 self.colorLayer = CALayer() self.colorLayer.frame = CGRectMake(0, 0, 100, 100) self.colorLayer.position = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2) self.colorLayer.backgroundColor = UIColor.redColor().CGColor self.view.layer.addSublayer(self.colorLayer) } } override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { // 获得触摸点 let point = (touches as NSSet).anyObject()?.locationInView(self.view) as CGPoint! // 检测是否点击了移动图层 if ((self.colorLayer.presentationLayer().hitTest != nil) { // 随机图层背景色 let red: CGFloat = CGFloat(arc4random / CGFloat let green: CGFloat = CGFloat(arc4random / CGFloat let blue: CGFloat = CGFloat(arc4random / CGFloat self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor } else { // 否则移动图层到新的位置 CATransaction.begin() CATransaction.setAnimationDuration self.colorLayer.position = point CATransaction.commit() } }}

种种图层的性情的突显值被积累在三个叫显示层的独门图层,那是由此-presentationLayer方式访问的。显示层本质上是模型层的副本,但它的属性值平日是日前时刻点的样子。用另简单的说,你能够访谈彰显层的属性来查六柱预测应模型图层属性在屏幕上的当前值。

CATransaction+begin+commit方法会在+animateWithDuration:animations:方法中间调用,动画闭包中的动画会在内部实行。所以任何你在闭包内做的天性改造会被专门的学业包涵。那样能够幸免开荒者错误的尚未将+begin+commit依次对应。

全盘搜索的结果会是-actionForKey:nil(此时,没有动画发生,属性值会立马改换)或三个死守CAAction说道的靶子,那是CALayer会用来在先前值和眼下值时期的卡通片的。

那看起来有一点太过好了,所以让大家用二个例子来演示它:大家将使用第1章“图层树”中的月光蓝方块项目,然后增加多少个开关设置图层为多少个随意颜色。表7.1显示了代码。点击按键你会看见颜色平滑对接而非跳转到另贰个新值。

让我们为大家的渐隐例子钦定二个分歧等的动作。大家会修改表7.1,为colorLayer安装贰个自定义的actions词典。大家能够利用委托来贯彻那一点,但actions词典方法需求更加少的代码。所以大家怎么样创建二个方便的动作对象?

咱俩得以用三个粗略的例子来演示后多个例子。在这些例子中,点击显示器上的别的地点会让图层以动画片的款式活动到点击处。点击图层自个儿会给它设置一个自便的颜色值。大家于图层的展现层上调用-hitTest:方式来判断点击是或不是在图层中。

率先有个不要呈报了颇具Core Animation可以达成的事物,除了动画。动画是Core Animation框架中二个一定生硬的片段。在这一章中,大家将看一下它的办事原理。极其的,大家批注隐式动画,那是框架自动运营的动画。

Core Animation借使显示屏上的享有东西就要运动。动画并非您在Core Animation启用的事物。动画必需出示的禁用,不然它们时时随处都会发生。

近年来让我们做个考试:不给单独子图层施加动画,大家平昔给视图的主图层施加动画。表7.4来得了修改后的代码版本,它从表7.第22中学移除了colorLayer并一贯设置layerView的主图层颜色。

你只怕注意到也可以有三个-modelLayer办法。在显示图层上调用-modelLayer会回到其下正值显示的CALayer。在八个一般性图层上调用modelLayer只会回到-self。(大家早就说过普通图层实际上正是一种模型。)

下一章中,大家将执教Core Animation提供的显式动画片类型,它能够直接用于图层属性动画或复写私下认可的图层行为。

倘若您改改代码来使-hitTest:措施直接在colorLayer上而非其出示图层上调用,你会开掘在图层移动时将不可能正常干活,那样你不得不点击图层就要移动到的职分来触发(那是为什么大家开始时代用展现层来扩充点击测验)。

不管哪一天你改换CALayer的可动画的习性,改造并不会立刻反映在显示器上。相反,图层属性通过动画平滑地过去叁个值过渡到新值。你不须求做什么样就足以使那总体发生;它们是默许行为。

在iOS中,荧屏每秒重绘伍16次。借使动画时间专长一秒的1/60,Core Animation为此会供给在荧屏上结合那些图层数次,次数在你设置可动画属性的新值和新值最终呈现在显示器上中间。那意味CALayer非得以一种办法保持除了当前品质的“实际”值之外的显示值。

Outside: <CABasicAnimation: 0x7ffa0b11a7b0>Inside: <CABasicAnimation: 0x7ffa0b08a060>Outside: <CABasicAnimation: 0x7ffa0ad070c0>Inside: <CABasicAnimation: 0x7ffa0ad821c0>

CALayer的本性表现并不平庸,改造图层属性并不会有叁个应声的效能,但随时间稳步更新。那是怎么样做到的啊?

有了那一个文化,我们得以很轻松地更换大家的颜色动画时间长度。使用+setAnimationDuration:主意来改造目前业务的时间长度足够了,但大家会先起来二个新工作来幸免退换时间长度带来不想要的副成效。更换方今政工作时间间长度恐怕影响其余同有的时候候产生的动画片,所以调解动画设置前显式入栈一个作业总是多个好主意。

正如预测的一致,UIView当属性在动画闭包外更改并为属性动作重返nil时会禁止使用隐式动画。当动画可用时回来的动作取决于属性类型,但在此处,它是CABasicAniamtion。(你会在第8章“显式动画”中学习这一点。)

CATransaction.setDisableActions

小结一下,大家学了那几个事物:

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

做小编发挥的,而非我说的。——Edna Krabappel, The Simpsons

CALayer在品质退换时自动施加的动画片叫动作。当CALayer的属性被涂改时,它会调用-actionForKey:艺术,传递当中的习性。接下来产生的在CALayer头文件中有总体的文书档案,但它最后总括如下:

那表明了UIKit是怎样禁止使用隐式动画的:各类UIView突显的疑似主图层的寄托,并提供叁个-actionForLayer:forKey方式的贯彻。当不在动画闭包中时,UIView为富有的图层动作再次回到nil,但在动画闭包的成效域中回到非空值。大家能够用多个小例子演示那点。

表7.4 直接设置主图层的属性import UIKitclass ViewController: UIViewController { @IBOutlet weak var layerView: UIView! override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 判断横屏 let screenSize = UIScreen.mainScreen().applicationFrame.size if (screenSize.width > screenSize.height) { // 直接设置我们layerView主图层的颜色 self.layerView.layer.backgroundColor = UIColor.blueColor().CGColor } } @IBAction func changeColor(sender: AnyObject) { // 开始新交易 CATransaction.begin() // 设置动画时长为1秒 CATransaction.setAnimationDuration // 随机图层背景色 let red: CGFloat = CGFloat(arc4random / CGFloat let green: CGFloat = CGFloat(arc4random / CGFloat let blue: CGFloat = CGFloat(arc4random / CGFloat self.layerView.layer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor // 执行交易 CATransaction.commit() }}

UIVIew听他们讲闭包的卡通片允许你提供三个成功闭包在动画甘休时调用。一样的特色在CATransaction接口中也是足以的,通过调用+setCompletionBlock:格局实现。让大家再一次修改先前的例子让颜色改造之后实施多个动作。大家将助长三个成就闭包,使用它触发每三个卡通来使图层每当颜色改动后旋转90度。表7.3显得了代码,图7.2来得了结果。

图片 6图7.2 颜色渐变完毕后选取的旋转动画

只要你运营那么些类型,你会小心到当开关按下后颜色马上跳转成二个新值而非像以前同一的坦荡动画。产生了怎样?隐式动画看起来好疑似在UIView的主图层中被剥夺了。

当你设置CALayer属性,你实际是在概念你想当前思想政治工作最终展现的模型Core Animation会如同控制器般担任更新这么些依照图层动作和事情设置的荧屏上的质量的视图状态。

大家领略Core Animaiton一般说来会给CALayer的有着属性别变化化扩张动画,但UIView以某种格局将它的主图层关闭了这一作为。为了领悟那些怎么发生的,大家先是必要知道隐式动画是怎么着兑现的。

任何可动画的图层属性改换变加多上栈顶的事情。你能够通过使用+setAnimationDuration:艺术设置当前政工动画时间长度,也许您能够选取+animationDuraion办法得知当前时间长度。(暗中同意为0.25秒。)

事务是Core Animation是用来归纳一多级特定属性动画的编制。任何可动画的图层属性有多少个加以事务的变动就不会马上改换,相反会在工作执行时初步动画过渡到新值。

想想看,大家也是有理会到要是每当UIView属性被改造时都会自行有动画。所以,假如UIKit是构建在Core Animaiton(它总是私下认可给另外东西加上动画)之上,UIKit的隐式动画怎么会暗中同意禁止使用?

当你改换属性时,Core Animation是什么样调整它将体现的卡通的档期的顺序和时间长度的?动画时间长度由近日事务安装,动画类型由图层动作控制。

我们在第1章有聊起到,除了图层树外有二个叫展示树的事物。显示树是三个由图层树中具备图层的显得图层组成的树。注意,突显层只在图层每贰回提交(正是当它首先次体将来显示器上时)时创建,所以在那以前尝试调用-presentationLayer会返回nil

在iOS4中,Apple为UIView增加了两个新的依赖闭包的卡通方法+animateWithDuration:animations:。它在语法上比分离属性动画的起初、停止代码块更为通透到底,但实在它在骨子里做同样的作业。

图片 7图7.3 使用推过渡完结的颜色值动画

表7.5 测试UIView的actionForLayer:forKey:实现import UIKitclass ViewController: UIViewController { @IBOutlet weak var layerView: UIView! override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 判断横屏 let screenSize = UIScreen.mainScreen().applicationFrame.size if (screenSize.width > screenSize.height) { // 测试动画闭包外的图层动作 let outsideAction = self.layerView.actionForLayer(self.layerView.layer, forKey: "backgroundColor") println("Outside: (outsideAction)") // 开始动画闭包 UIView.beginAnimations(nil, context: nil) // 测试动画闭包内的图层动作 let insideAction = self.layerView.actionForLayer(self.layerView.layer, forKey: "backgroundColor") println("Inside: (insideAction)") // 结果动画闭包 UIView.commitAnimations() } }}
  • UIView的主图层禁止使用陷式动画。主图层属性动画的独一方法是使用UIView动画片方法(实际不是依附CATransaction),子类化UIView再便是重写-actionForLayer:forKey:方法,或创立叁个显式动画。
  • 对此有主图层,大家得以经过兑现-actionForLayer:forKey:图层代理方法大概提供actions词典来调控隐式属性动画。

事情使用CATransaction类管理。CATransaction类有二个想不到的设计,它并不比名字所示的单纯业务,而是管理着一群事务而从不给您一贯的会见。CATransaction尚未质量或实例方法,你无法健康使用+alloc-init来成立三个事情。相反,你利用类措施+begin+commit来使一个新业务入栈顶或使当前作业出栈。

  1. 图层首先检查它是还是不是有嘱托,固然委托实现了CALayerDelegate说道中钦命的-actionForLayer:forKey措施。借使是,则调用它并赶回结果。
  2. 如若没有嘱托,或委托未有兑现-actionForLayer:forKey措施,图层检查它的actions词典,那一个词典包罗了属性名与动作的投射。
  3. 如果actions词典未有另外供给的习性入口,图层会寻觅它的style词典档期的顺序来寻找任何相称属性名的动作。
  4. 最后,如果在style档期的顺序中找不到符合的动作,图层会回调-defualtActionForKey:方法,那是给属性定义规范动作的。

当大家运营项目时,大家会在调整高雄看见这几个:

表7.2 使用CATransaction控制动画时长@IBAction func changeColor(sender: AnyObject) { // 开始新事务 CATransaction.begin() // 设置动画时长为1秒 CATransaction.setAnimationDuration // 随机图层背景色 let red: CGFloat = CGFloat(arc4random / CGFloat let green: CGFloat = CGFloat(arc4random / CGFloat let blue: CGFloat = CGFloat(arc4random / CGFloat self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor // 执行事务 CATransaction.commit()}
表7.1 随机图层颜色import UIKitclass ViewController: UIViewController { @IBOutlet weak var layerView: UIView! var colorLayer: CALayer! override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 判断横屏 let screenSize = UIScreen.mainScreen().applicationFrame.size if (screenSize.width > screenSize.height) { // 创建子图层 self.colorLayer = CALayer() self.colorLayer.frame = CGRectMake(50.0, 50.0, 100.0, 100.0) self.colorLayer.backgroundColor = UIColor.blueColor().CGColor // 加到视图中 self.layerView.layer.addSublayer(self.colorLayer) } } @IBAction func changeColor(sender: AnyObject) { // 随机图层背景色 let red: CGFloat = CGFloat(arc4random / CGFloat let green: CGFloat = CGFloat(arc4random / CGFloat let blue: CGFloat = CGFloat(arc4random / CGFloat self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor }}

小编们在辩论是的快捷的MVC模式。CALayer是叁个您平凡会用于MVC(模型-视图-调节器)方式中客商分界面(也叫视图)部分的可视化类,但在顾客分界面自个儿的前后文中,CALayer表现的更疑似三个模型,它标识在具备动画停止后视图将在展现的指南。事实上,在Apple本人的文档中,图层树一时也指模型图层树。

表7.6 实现自定义动作import UIKitclass ViewController: UIViewController { @IBOutlet weak var layerView: UIView! var colorLayer: CALayer! override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 判断横屏 let screenSize = UIScreen.mainScreen().applicationFrame.size if (screenSize.width > screenSize.height) { // 创建子图层 self.colorLayer = CALayer() self.colorLayer.frame = CGRectMake(50.0, 50.0, 100.0, 100.0) self.colorLayer.backgroundColor = UIColor.blueColor().CGColor // 添加自定义动作 let transition = CATransition() transition.type = kCATransitionPush transition.subtype = kCATransitionFromLeft self.colorLayer.actions = ["backgroundColor": transition] // 添加进视图中 self.layerView.layer.addSublayer(self.colorLayer) } } @IBAction func changeColor(sender: AnyObject) { // 随机图层背景色 let red: CGFloat = CGFloat(arc4random / CGFloat let green: CGFloat = CGFloat(arc4random / CGFloat let blue: CGFloat = CGFloat(arc4random / CGFloat self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor }}

假定您曾采取UIView的卡通方法达成任何动画,那个方式看起来应当很谙习。UIView有多少个法子+beginAnimations:context:+commitAnimations,它们工作规律类似于CATransaction中的+begin+commite方法。你在+beginAnimations:context:+commitAnimations中退换的有着视图或图层属性会自动发出动画,那是因为那几个UIView动画片方法其实正是在装置二个CATransaction

对接就要第8章详细解释,但这里丰裕表达CATransition遵循CAAction共谋,可认为此被当做图层动作使用。结果足够光彩夺目;无论曾几何时大家转移大家的图层颜色,新的值将从侧面滑入并非暗中认可的陆陆续续渐变效果。

当您转移图层的性质时,属性值自己其实是立时更新的(借使您品味读取它,你会发掘其值是你刚刚安装的),但改动并未显示器上反映出去。那是因为你设置的属性并不直接改变图层的指南;相反,它钦命了图层在性质动画完结后将要有的样子。

返回nil实际不是禁止使用隐式动画的当世无双方法;CATransaction有多少个格局叫+setDisableActions:能够用来还要启用或剥夺全数属性的卡通。若是我们修改表7.2的代码,增添上边几行在CATransaction.begin()前边,它会阻拦全部动画爆发:

这一章讲明了隐敝动画以及Core Animation为一个点名属性采取适合动画动作的编写制定。你也学习了UIKit何以利用Core Animation的隐式动画机制来增添其自己的显式系统的,在显示系统中卡通是默许禁止使用的,只有在急需时启用。最后,你学习了显示图层和模型图层,以及它们怎样使Core Animation何况追踪图层当前和前日的职位。

表7.3 当颜色动画结束时增加回调@IBAction func changeColor(sender: AnyObject) { // 开始新事务 CATransaction.begin() // 设置动画时长为1秒 CATransaction.setAnimationDuration // 结束时增加旋转动画 CATransaction.setCompletionBlock({ // 图层旋转90度 var transform = self.colorLayer.affineTransform() transform = CGAffineTransformRotate(transform, CGFloat self.colorLayer.setAffineTransform(transform) }) // 随机图层背景色 let red: CGFloat = CGFloat(arc4random / CGFloat let green: CGFloat = CGFloat(arc4random / CGFloat let blue: CGFloat = CGFloat(arc4random / CGFloat self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor // 执行事务 CATransaction.commit()}

图片 8图7.4 多个平移图层的体现与模型的关系.png

本文由永利皇宫463登录发布于编程,转载请注明出处:关于隐式动画,隐式动画

关键词: