• 动画基础(隐式动画)


    CATransaction

    隐式动画:(我们并没有指定任何动画的类型。我们仅仅改变了一个属性,然后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秒的动画。

    --我们当然可以用当前事务的+setAnimationDuration:方法来修改动画时间,但在这里我们首先起一个新的事务,于是修改时间就不会有别的 副作用。因为修改当前事务的时间可能会导致同一时刻别的动画(如屏幕旋转),所以最好还是在调整动画之前压入一个新的事务 。

    修改动画属性,产生动画的机制:

    我们把改变属性时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做个简单的实验

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

    打印:

    2016-05-12 17:19:19.192 足球数据测试[3013:164607] Outside: <null>
    2016-05-12 17:19:19.193 足球数据测试[3013:164607] Inside: <CABasicAnimation: 0x7ff490c026a0>

    结论:

    当属性在动画块之外发生改变,UIView直接通过返回nil来禁用隐式动画。但如果在动画块范围之内,根据动画具体类型返回相应的属性,在这个例子就是CABasicAnimation

    当然返回nil并不是禁用隐式动画唯一的办法,CATransacition有个方法叫做+setDisableActions:,可以用来对所有 属性打开或者关闭隐式动画。如果在清单7.2的[CATransaction begin]之后添加下面的代码,同样也会阻止动画的发生:

    1
    [CATransaction setDisableActions:YES];

    总结一下,我们知道了如下几点

    • UIView 关联的图层禁用了隐式动画,对这种图层做动画的唯一办法就是使用UIView的动画函数(而不是依赖CATransaction),或者继承 UIView,并覆盖-actionForLayer:forKey:方法,或者直接创建一个显式动画(具体细节见第八章)。

    • 对于单独存在的图层,我们可以通过实现图层的-actionForLayer:forKey:委托方法,或者提供一个actions字典来控制隐式动画。

    使用不同的动画行为:

    我们来对颜色渐变的例子使用一个不同的行为,通过给colorLayer设置一个自定义的actions字典。我们也可以使用委托来实现,但是actions字典可以写更少的代码。那么到底改如何创建一个合适的行为对象呢?

    行为通常是一个被Core Animation隐式调用的显式动画对象。这里我们使用的是一个实现了CATransaction的实例,叫做推进过渡。

    - (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;
    }
    不论在什么时候改变背景颜色,新的色块都是从左侧滑入,而不是默认的渐变效果。

    ----委托来实现

    -(id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
    {
        if ([event isEqualToString:@"backgroundColor"]) {
            CATransition *transition = [CATransition animation];
            transition.type = kCATransitionPush;
            transition.subtype = kCATransitionFromLeft;
            return transition;
        }
        else
        {
            return nil;
        }
        
    }

  • 相关阅读:
    [转]asp.net页面缓存技术
    UL和LI在div中的高度的IE6下兼容性
    jquery制作的横向图片滚动带横向滚动条TackerScroll
    电脑可以上网,但是qq登陆不上去?
    Introduction to discrete event system学习笔记4.6
    Introduction to Discrete event system学习笔记4.9
    Introduction to discrete event systemsstudy 4.5
    Symbolic synthesis of obserability requirements for diagnosability B.Bittner,M.Bozzano,A.Cimatti,and X.Olive笔记4.16
    Introduction to discrete event system学习笔记4.8pm
    Introduction to discrete event system学习笔记 4.8
  • 原文地址:https://www.cnblogs.com/jingdizhiwa/p/5486671.html
Copyright © 2020-2023  润新知