如何禁用CALayer隐式动画?

Ese*_*her 37 animation calayer ios

这让我疯狂!我正在制作绘图应用程序.假设我正在制作一张UIView名片.

我在这个视图([sheet.layer addSublayer:...])中添加了一些子图层然后我想要绘制它们.为此,我正在创建一个CGImageRef并将其放入图层中contents.但它是动画的,我不希望这样.

我尝试了一切:

  • removeAnimationForKey:
  • removeAllAnimations
  • 设置动作字典
  • 使用动作层 delegate
  • [CATransaction setDisableAnimations:YES]

这似乎是正确的.我不明白为什么这个图层仍然是动画的; _;
难道我做错了什么?有秘密的方式吗?

Oli*_*one 38

您必须通过将代码包装在CATransaction中来显式禁用动画

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
                 forKey:kCATransactionDisableActions];
layer.content = someImageRef;
[CATransaction commit];
Run Code Online (Sandbox Code Playgroud)


Sur*_*gch 33

迅速

CATransaction.begin()
CATransaction.setDisableActions(true)

// change layer properties that you don't want to animate

CATransaction.commit()
Run Code Online (Sandbox Code Playgroud)


zne*_*eak 15

从Mac OS X 10.6和iOS 3开始,CATransaction还有一个setDisableActions设置key值的方法kCATransactionDisableActions.

[CATransaction begin];
[CATransaction setDisableActions:YES];

layer.content = someImageRef;

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

在Swift中,我喜欢使用这种扩展方法:

extension CATransaction {
    class func withDisabledActions<T>(_ body: () throws -> T) rethrows -> T {
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        defer {
            CATransaction.commit()
        }
        return try body()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

CATransaction.withDisabledActions {
    // your stuff here
}
Run Code Online (Sandbox Code Playgroud)


小智 12

其他方式:

  1. 您应该禁用sheet.layer的默认动画,在添加子图层时会隐式调用它.

  2. 您还应该对每个子图层进行内容动画处理.当然,每次设置sublayer.content时都可以使用CATransaction的"kCATransactionDisableActions".但是,您可以在创建子图层时禁用此动画一次.


这是代码:

// disable animation of container
sheet.layer.actions = [NSDictionary dictionaryWithObject:[NSNull null] 
                                                  forKey:@"sublayers"];

// disable animation of each sublayer
sublayer.layer.actions = [NSDictionary dictionaryWithObject:[NSNull null] 
                                                     forKey:@"content"];

// maybe, you'll also have to disable "onOrderIn"-action of each sublayer.       
Run Code Online (Sandbox Code Playgroud)

  • 对于寻找这种答案的人(如我),但在 Swift 中,格式为:`layer.actions = ["sublayers":NSNull()]` (3认同)
  • 毫无疑问,这与奥利弗的答案一样好。更好,恕我直言。 (2认同)

Ole*_*nov 6

层扩展:

extension CALayer {    
    var areAnimationsEnabled: Bool {
        get { delegate == nil }
        set { delegate = newValue ? nil : CALayerAnimationsDisablingDelegate.shared }
    }
}

private class CALayerAnimationsDisablingDelegate: NSObject, CALayerDelegate {
    static let shared = CALayerAnimationsDisablingDelegate()
    private let null = NSNull()

    func action(for layer: CALayer, forKey event: String) -> CAAction? {
        null
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

anyLayer.areAnimationsEnabled = false
Run Code Online (Sandbox Code Playgroud)


Ska*_*aal 5

Swift 4扩展名:

extension CATransaction {

    static func disableAnimations(_ completion: () -> Void) {
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        completion()
        CATransaction.commit()
    }

}
Run Code Online (Sandbox Code Playgroud)

用法:

    CATransaction.disableAnimations {
        // things you don't want to animate
    }
Run Code Online (Sandbox Code Playgroud)