CALayer的隐式动画

CALayer的隐式动画

当你改变CALayer的一个可做动画的属性(例如backgroundColor背景颜色),它并不能立刻在屏幕上体现出来。相反,它是从先前的值平滑过渡到新的值(动画)。这一切都是默认的行为,你不需要做额外的操作。

CATransaction事务

CALayer的隐式动画通过CATransaction事务实现

  • 如果你用过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匹配的失误造成的风险。
  • 基于UIViewblock的动画允许你在动画结束的时候提供一个完成的动作。CATransaction接口提供的+setCompletionBlock:方法也有同样的功能。
    // 开启事务
    [CATransaction begin];
    // 设置动画时间
    [CATransaction setAnimationDuration:1.0];
    // 执行完成后调用
    [CATransaction setCompletionBlock:^{
    
    
        // 旋转90度
        CGAffineTransform transform = self.colorLayer.affineTransform;
        transform = CGAffineTransformRotate(transform, M_PI_2);
        self.colorLayer.affineTransform = transform;
    }];
    // 随机颜色
    CGFloat red = arc4random() / (CGFloat)INT_MAX;
    CGFloat green = arc4random() / (CGFloat)INT_MAX;
    CGFloat blue = arc4random() / (CGFloat)INT_MAX;
    // 修改Layer的背景颜色
    self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
    // 提交事务
    [CATransaction commit];

图层行为(默认禁用了CALayer的隐式动画)

  • CATransaction事务设置UIView关联layer的背景色动画失效
    // ⚠️该例子无动画效果,CATransaction对直接设置UIView的Layer层动画失效
    // 开启事务
    [CATransaction begin];
    // 设置动画时间
    [CATransaction setAnimationDuration:1.0];
    // 随机颜色
    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;
    // 提交事务
    [CATransaction commit];
  • UIKit是如何禁用隐式动画
  • 每个UIView对它关联的图层都扮演了一个委托,并且提供了-actionForLayer:forKey的实现方法。当不在一个动画块的实现中,UIView对所有图层行为返回nil,但是在动画block范围之内,它就返回了一个非空值
	// 输出UIView的 actionForLayer:forKey:方法
    NSLog(@"Outside: %@", [self.layerView actionForLayer:self.layerView.layer forKey:@"backgroundColor"]);
    // 开始动画
    [UIView beginAnimations:nil context:nil];
    // 输出UIView的 actionForLayer:forKey:方法
    NSLog(@"Inside: %@", [self.layerView actionForLayer:self.layerView.layer forKey:@"backgroundColor"]);
    // 结束动画
    [UIView commitAnimations];
  • 在动画block范围之内UIView返回CABasicAnimation动画类型
控制台输出:
$ LayerTest[21215:c07] Outside: <null>
$ LayerTest[21215:c07] Inside: <CABasicAnimation: 0x757f090>
  • 当然返回nil并不是禁用隐式动画唯一的办法,CATransacition有个方法叫做+setDisableActions:,可以用来对所有属性打开或者关闭隐式动画
	// 在使用CATransaction时添加,可以阻止动画发生
	[CATransaction setDisableActions:YES];

总结

  • UIView关联的图层禁用了隐式动画,对这种图层做动画的唯一办法就是使用UIView的动画函数(而不是依赖CATransaction),或者继承UIView,并覆盖-actionForLayer:forKey:方法,或者直接创建一个显式动画
  • 对于单独存在的图层,我们可以通过实现图层的-actionForLayer:forKey:委托方法,或者提供一个actions字典来控制隐式动画
	// 通过actions字典控制隐式动画
    CALayer *colorLayer = [CALayer layer];
    colorLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
    colorLayer.backgroundColor = [UIColor blueColor].CGColor;
    // Layer添加CATransition
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromLeft;
    colorLayer.actions = @{
    
    @"backgroundColor": transition};
	// UIView添加Layer
	UIView *layerView = [[UIView allow] init];
    [layerView.layer addSublayer:self.colorLayer];
    // 这个时间修改Layer层的backgroundColor,自带动画

呈现与模型

  • 当你改变一个图层的属性,属性值的确是立刻更新的(如果你读取它的数据,你会发现它的值在你设置它的那一刻就已经生效了),但是屏幕上并没有马上发生改变。这是因为你设置的属性并没有直接调整图层的外观,相反,他只是定义了图层动画结束之后将要变化的外观
  • 当设置CALayer的属性,实际上是在定义当前事务结束之后图层如何显示的模型
  • presentationLayer:它的属性值代表了在任何指定时刻当前外观效果。换句话说,你可以通过呈现图层的值来获取当前屏幕上真正显示出来的值,presentationLayer是被提交(就是首次第一次在屏幕上显示)的时候创建,所以在那之前调用presentationLayer将会返回nil
  • hitTest:方法来判断指定图层是否被触摸,这时候对呈现图层而不是模型图层调用hitTest会显得更有意义,因为呈现图层代表了用户当前看到的图层位置,而不是当前动画结束之后的位置

参考资料

《iOS核心动画高级技巧》

猜你喜欢

转载自blog.csdn.net/weixin_46926959/article/details/127622798
今日推荐