それは私を夢中にさせています!私は描画アプリケーションに取り組んでいます。 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];
スウィフト
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
}
別の方法:
サブレイヤーを追加するときに暗黙的に呼び出される、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.
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
}
Swift 2
次のようにすべてのアニメーションを無効にすることができました。ここで、myView
は作業しているビューです。
myView.layer.sublayers?.forEach { $0.removeAllAnimations() }
補足として、すべてのレイヤーを削除します。
myView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
これは古い質問ですが、問題は残っています。場合によっては、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
}
}
/**
* 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()
}
このコードをコードの任意の場所に追加します(グローバルスコープ)
レイヤー拡張:
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
私はライアンに完全に同意します。彼の答えはMacOSです。iOSの場合は、次を追加してNSNull()アクションを作成します。この質問 -[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)
}
前 _[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"]];
}
_