有选择地覆盖CALayer隐式动画

时间:2011-04-08 00:51:28

标签: cocoa core-animation

我有一个CALayer子类,它被约束到父图层的宽度,但是固定的高度。我希望禁用隐式动画来调整窗口大小,但每当我设置图层的高度时都会启用。

要在调整窗口大小时禁用动画,我将图层操作设置为

NSMutableDictionary *actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"bounds", [NSNull null], @"position", nil];

这似乎有效。然后我重写了我的图层子类

中的actionForKey:方法
- (id<CAAction>)actionForKey:(NSString *)event
{
    if ([event isEqualToString:@"frame.size.height"]) {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"frame.size.height"];
        [animation setDuration:0.5f];
        return animation;
    }
    return nil;
}

但是当我用

更改图层的高度时
[layer setValue:[NSNumber numberForFloat:50.0] forKey:@"frame.size.height"];

高度发生变化,但不是动画。我看到使用frame.size.height调用actionForKey:方法,但无论我返回什么,它都不会动画。如果我没有设置动作,或者使用actionForKey:方法,高度会正确设置动画,但是窗口调整大小也是动画的,我不想要。

另外,也许我误解了,但我想从actionForKey返回nil:会使默认动画运行,但看起来即使方法的存在也会停止所有隐式动画(是否设置了动作词典) 。

我在这里错过了什么,我会感激任何指示。

2 个答案:

答案 0 :(得分:3)

您的子类将为每个键调用actionForKey:,因此如果您返回nil,则不会对该键执行操作。如果您需要默认动画,则应返回[super actionForKey:event][CALayer defaultActionForKey:event]

图层的frame是根据boundsposition计算出来的,所以如果这两个图片没有动画,则frame就不会有动画。*

您想要做的是:

[CATransaction setValue:kCFBooleanTrue
                 forKey:kCATransactionDisableActions]

当您的图层因窗口大小调整而调整大小时。这将暂时禁用动画(对于此事务);当您直接更改图层的大小时,它仍然会生成动画。我不确定这个电话的正确位置是什么;我只是尝试在窗口调整大小的通知中进行回调,但这不起作用。我相信你找出把它放在你的代码中的位置并不会太难。


*:事实上,文档说:

  

注意:frame属性不能直接设置动画。相反,您应该设置边界,anchorPoint和位置属性的适当组合的动画,以实现所需的结果。

答案 1 :(得分:2)

有,正如他们所说的那样......有几种方法可以使这只猫皮肤 ......通过在图层的“动作”词典中设置一些条目,我找到了最简单的方法之一。

CALayer *stopAnimatingLikeThat = CALayer.new;
stopAnimatingLikeThat.actions  =
  @{ @"position":NSNull.null, @"bounds":NSNull.null };

这将阻止烦人的“陷入困境”,“隐含动画”等界限的变化等等。