这让我发疯了!我正在制作绘图应用程序。假设我正在处理一张名为UIView
的表格。
我在这个视图中添加了一些子图层([sheet.layer addSublayer:...]
)然后我想要绘制它们。为此,我创建了一个CGImageRef
并将其放入图层contents
。但它是动画的,我不希望这样。
我尝试了一切:
removeAnimationForKey:
removeAllAnimations
delegate
[CATransaction setDisableAnimations:YES]
这似乎是正确的。我不明白为什么这个图层仍然是动画的; _;
难道我做错了什么?有秘密的方式吗?
答案 0 :(得分:37)
您必须通过将代码包装在CATransaction
中来显式禁用动画[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
layer.content = someImageRef;
[CATransaction commit];
答案 1 :(得分:27)
<强>夫特强>
CATransaction.begin()
CATransaction.setDisableActions(true)
// change layer properties that you don't want to animate
CATransaction.commit()
答案 2 :(得分:15)
从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
}
答案 3 :(得分:11)
另一种方式:
您应该禁用sheet.layer的默认动画,在添加子图层时会隐式调用它。
您还应该对每个子图层进行内容动画处理。当然,每次设置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.
答案 4 :(得分:1)
Swift 2
我可以按如下方式禁用所有动画,其中myView
是您正在使用的视图:
myView.layer.sublayers?.forEach { $0.removeAllAnimations() }
作为旁注,删除所有图层:
myView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
答案 5 :(得分:1)
/**
* 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()
}
在代码中的任何位置添加此代码(全局范围)
答案 6 :(得分:1)
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
}
答案 7 :(得分:0)
之前,使用[self.layer addSublayer:yourCALayer]
将图层添加到视图中,也可以在添加图层之后,通过覆盖动画键来禁用CALayer的特定动画属性。设置为NULL的键以该属性命名,如layer.position = CGPoint(x,y);
yourCALayer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"position"];
由于actions
属性是一个NSDictionary,它不允许存储nil
,因此您可以使用[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"]];
}
答案 8 :(得分:0)
这是一个古老的问题,但问题仍然存在。有时您不希望CALayer强制执行的动画。我对基于事务的方法不满意,因为我只想关闭这些操作。为了好这是CALayer子类的Swift 4解决方案,它允许选择是允许任何操作还是全局禁用它们。您还可以创建具有相同内容的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
}
}
答案 9 :(得分:0)
我完全同意赖安。他的答案是针对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)
}
答案 10 :(得分:0)
图层扩展:
extension CALayer {
var areAnimationsEnabled: Bool {
set {
delegate = newValue ? nil : CALayerAnimationsDelegate.shared
}
get {
return delegate == nil
}
}
}
fileprivate class CALayerAnimationsDelegate: NSObject, CALayerDelegate {
static let shared = CALayerAnimationsDelegate()
private let null = NSNull()
func action(for layer: CALayer, forKey event: String) -> CAAction? {
return null
}
}
用法:
anyLayer.areAnimationsEnabled = false