【问题标题】:Selectively overriding CALayer implicit animations选择性地覆盖 CALayer 隐式动画
【发布时间】:2011-04-08 00:51:27
【问题描述】:

我有一个 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 会使默认动画运行,但似乎即使该方法的存在也会停止所有隐式动画(无论操作字典是否设置) .

我在这里缺少什么,我将不胜感激。

【问题讨论】:

    标签: cocoa core-animation


    【解决方案1】:

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

    一个层的frame是从它的boundsposition计算出来的,所以如果这两个没有动画,frame就没有动画。*

    你想做的是:

    [CATransaction setValue:kCFBooleanTrue
                     forKey:kCATransactionDisableActions]
    

    当您的图层因窗口大小调整而调整大小时。这将在这次禁用动画(对于此事务);当您直接更改图层的大小时,它仍然会动画。我不确定打那个电话的正确位置是什么;我只是尝试在通知窗口正在调整大小的回调中执行此操作,但这不起作用。我相信你不会很难弄清楚将它放在代码中的什么位置。


    *:事实上,文档说:

    注意:frame 属性不能直接设置动画。相反,您应该对 bounds、anchorPoint 和 position 属性的适当组合进行动画处理,以获得所需的结果。

    【讨论】:

    • 谢谢你,这一切都清楚了。我最终继承了 CAConstraintsLayoutManager 并禁用了 layoutSublayersOfLayer: 方法中的操作。它似乎有效,虽然我不知道这是否是最好的方法。
    • 听起来不错。我让我的观点本身采用CALayoutManager 协议来处理一个相关的、稍微简单的案例。很高兴我能帮上忙。
    • 如果你禁用父层的 layoutSublayers 方法中的操作,它似乎也可以工作。
    【解决方案2】:

    有,正如他们所说.. 给这只猫剥皮的几种方法...我发现其中一种最容易...通过在图层的“动作”字典中设置一些条目。 .

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

    这将阻止边界变化等烦人的“卡在蜂蜜中”“隐式动画”等。

    【讨论】:

    • 这是一个很好的方法,因为您可以将 CALayer 设置为在初始化时不调整位置和边界的大小。
    • 在没有隐式动画的图层中重绘文本yourLayer.actions = @{ @"contents":NSNull.null };
    猜你喜欢
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 2011-03-16
    • 2016-05-16
    • 2011-08-15
    相关资源
    最近更新 更多