这让我疯狂!我正在制作绘图应用程序。假设我正在制作一张叫做表格的UIView
。
我在这个视图中添加了一些子图层([sheet.layer addSublayer:...]
)然后我想要绘制它们。为此我创建了一个CGImageRef
并将其放入图层的contents
中。但它是动画的,我不希望这样。
我尝试了一切:
removeAnimationForKey:
removeAllAnimations
delegate
[CATransaction setDisableAnimations:YES]
这似乎是正确的。我不明白为什么这个图层仍然是动画的; _; 难道我做错了什么?有秘密的方式吗?
您必须通过将代码包装在CATransaction中来显式禁用动画
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
layer.content = someImageRef;
[CATransaction commit];
我完全赞同瑞安。他的答案是MacOS,对于iOS,你添加以下内容来创建一个NSNull()动作。这个问题Disabling implicit animations in -[CALayer setNeedsDisplayInRect:]和标题中的文档引导我在这里
// Disable the implicit animation for changes to position
override open class func defaultAction(forKey event: String) -> CAAction? {
if event == #keyPath(position) {
return NSNull()
}
return super.defaultAction(forKey: event)
}
迅速
CATransaction.begin()
CATransaction.setDisableActions(true)
// change layer properties that you don't want to animate
CATransaction.commit()
从Mac OS X 10.6和iOS 3开始,CATransaction
还有一个setDisableActions
方法,用于设置关键kCATransactionDisableActions
的值。
[CATransaction begin];
[CATransaction setDisableActions:YES];
layer.content = someImageRef;
[CATransaction commit];
在Swift中,我喜欢使用这种扩展方法:
extension CATransaction {
class func withDisabledActions<T>(_ body: () throws -> T) rethrows -> T {
CATransaction.begin()
CATransaction.setDisableActions(true)
defer {
CATransaction.commit()
}
return try body()
}
}
然后你可以像这样使用它:
CATransaction.withDisabledActions {
// your stuff here
}
其他方式:
这是代码:
// 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.
Swift 4扩展:
extension CATransaction {
static func disableAnimations(_ completion: () -> Void) {
CATransaction.begin()
CATransaction.setDisableActions(true)
completion()
CATransaction.commit()
}
}
用法:
CATransaction.disableAnimations {
// things you don't want to animate
}
斯威夫特2
我可以按如下方式禁用所有动画,其中myView
是您正在使用的视图:
myView.layer.sublayers?.forEach { $0.removeAllAnimations() }
作为旁注,删除所有图层:
myView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
/**
* Disable Implicit animation
* EXAMPLE: disableAnim{view.layer?.position = 20}//Default animation is now disabled
*/
func disableAnim(_ closure:()->Void){
CATransaction.begin()
CATransaction.setDisableActions(true)
closure()
CATransaction.commit()
}
在代码中的任何位置添加此代码(全局范围)
这是一个老问题,但问题仍然存在。有时候你不想要CALayer强加给你的动画。我对基于交易的方法不满意,因为我只想关闭这些操作。好的。这是一个Swift 4解决方案,用于子类CALayer,允许选择是允许任何操作还是全局禁用它们。您还可以使用相同的内容创建CAShapeLayer,CATextLayer子类:
public class ActionCALayer: CALayer {
public var allowActions: Bool = false
override public func action(forKey event: String) -> CAAction? {
return allowActions ? super.action(forKey: event) : nil
}
}
在使用[self.layer addSublayer:yourCALayer]
将图层添加到视图之前,并且在已添加图层之后,您可以通过覆盖动画密钥来禁用CALayer的特定动画属性。您设置为NULL的键以属性命名,此处显示为layer.position = CGPoint(x,y);
的完成
yourCALayer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"position"];
因为actions
属性是一个不允许存储nil
的NSDictionary,所以你可以使用[NSNull null]
将它显式设置为NULL对象,这与(id)kCFNull
相同。你可以通过遍历视图层的所有子层来为所有子层执行此操作。 。
for (CALayer *iterationLayer in self.layer.sublayers ) {
iterationLayer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"position"];
//or for multiple keys at once
NSNull *nop = [NSNull null];
iterationLayer.actions = [NSDictionary dictionaryWithObjects:@[nop,nop] forKeys:@[@"position",@"contents"]];
}