CAGradientLayer属性不在UIView动画块中设置动画

Six*_*tto 13 core-animation uiview ios cagradientlayer

我有一种感觉,我忽略了一些基本的东西,但有什么更好的方法来找到它而不是在互联网上出错?

我有一个相当基本的用户界面.我的视图UIViewController是一个子类,+layerClassCAGradientLayer.根据用户的操作,我需要移动一些UI元素,并更改背景渐变的值.代码看起来像这样:

[UIView animateWithDuration:0.3 animations:^{
  self.subview1.frame = CGRectMake(...);
  self.subview2.frame = CGRectMake(...);
  self.subview2.alpha = 0;

  NSArray* newColors = [NSArray arrayWithObjects:
                         (id)firstColor.CGColor,
                         (id)secondColor.CGColor,
                         nil];
  [(CAGradientLayer *)self.layer setColors:newColors];
}];
Run Code Online (Sandbox Code Playgroud)

问题是我在这个块中对子视图所做的更改动画就好了(东西移动和淡化),但渐变颜色的变化却没有.它只是交换.

现在,文档确实说动画块中的Core Animation代码不会继承块的属性(持续时间,缓动等).但是,根本没有定义动画交易吗?(文档的含义似乎是你会得到一个默认动画,我得不到.)

必须使用显式CAAnimation来完成这项工作吗?(如果是这样,为什么?)

Six*_*tto 13

这里似乎有两件事情.第一个(正如Travis正确指出的那样,文档说明)是UIKit动画似乎对应用于CALayer属性更改的隐式动画没有任何影响.我认为这很奇怪(UIKit 必须使用Core Animation),但它就是它.

对于该问题,这是一个(可能非常愚蠢?)解决方法:

  NSTimeInterval duration = 2.0; // slow things down for ease of debugging
  [UIView animateWithDuration:duration animations:^{
    [CATransaction begin];
    [CATransaction setAnimationDuration:duration];

    // ... do stuff to things here ...

    [CATransaction commit];
  }];
Run Code Online (Sandbox Code Playgroud)

另一个关键是这个渐变图层是我视图的图层.这意味着我的视图是图层的委托(如果渐变图层只是一个子图层,它将没有委托).并为事件的UIView实现-actionForLayer:forKey:返回.(可能每个事件都不在特定的UIView动画列表中.)NSNull"colors"

将以下代码添加到我的视图将导致颜色更改按预期动画:

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
  id<CAAction> action = [super actionForLayer:layer forKey:event];
  if( [@"colors" isEqualToString:event]
      && (nil == action || (id)[NSNull null] == action) ) {
    action = [CABasicAnimation animationWithKeyPath:event];
  }
  return action;
}
Run Code Online (Sandbox Code Playgroud)