IOS 开发- 隐式动画

Do What I mean, not what I say

Implicit Animations

首先看一个demo

@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]
}
@end

在这个程序中,我们并没有看到任何代码和动画相关。我们只是单纯的更改了一个非UIView关联的Layer的属性(一定要是非UIView相关联的Layer,后文会解释原因)。当我们改变一个属性时,Core Animation是怎么判断动画类型和持续时间呢?实际上动画执行的时间取决于当前事务(Transaction)的设置,动画类型取决于图层行为(Layer Action)。事务实际上是Core Animation用来包含一系列动画集合的机制,任何时候在一个指定事务中去改变都不会立刻发生变化,而是当事务提交的时候开始用一个动画过渡到新值。事务是通过CATransation 类来管理的,这个类的设计很有意思,不像它的名字,它管理了一个你不能直接访问的事务的栈。CATransaction没有属性或者实例方法,并且也不能使用alloc,init来创建。然而,你可以通过类方法,+begin和+commit来把一个新的事务压入栈中,或者推出当前事件。

任何的一个可动画的图层的属性的变化都会被添加到栈顶的事务。(Any layer property change that can be animated will be added to the topmost transaction in the stack.)你可以通过+setAnimationDuration: 方法来设置当前事务的动画时间,或者,通过+animationDuration 方法来获取当前的动画时间。

Core Animation 在每一个run loop周期中自动开始一个新的事务,即是你不显示的使用[CATransaction begin]开始一个新的事务,任何一次在run loop循环中属性的改变都会被集中起来,然后坐一次0.25秒的动画。明白了这些之后,我们就可以轻松的修改变色动画的时间了,我们当然可以使用当前事务的+setAnimationDuration:方法来修改动画持续时间,但是我们先起一个新的事务,这样的话修改时间就不会产生副作用,因为修改当前事务的时间可能会影响统一时刻的其他动画,所以最好还是在调整动画之前压入一个新的事务。

- (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
    //commit the transaction
    [CATransaction commit]; 
}

完成块
基于UIView的block动画允许你在动画结束的时候提供一个完成块。CATransaction接口提供的+setCompleteBlock:方法也有同样的功能。

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

注意,旋转动画要比颜色渐变快得多,这事因为完成块是在颜色渐变得事务提交并出栈之后才被执行,所以,用默认的事务做变换,默认的时间也变成了0.25秒。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,141评论 5 13
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,551评论 6 30
  • 前言 本文只要描述了iOS中的Core Animation(核心动画:隐式动画、显示动画)、贝塞尔曲线、UIVie...
    GitHubPorter阅读 3,651评论 7 11
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,142评论 1 23
  • 在前面的学习中,我们讨论了CoreAnimation除了动画外可以做到的任何事情。但是动画是CoreAni...
    小猫仔阅读 1,539评论 0 0