Ça me rend fou! Je travaille sur une application de dessin. Disons que je travaille sur une feuille UIView
appelée.
J'ajoute quelques sous-couches à cette vue ([sheet.layer addSublayer:...]
), puis je souhaite y dessiner. Pour ce faire, je crée une variable CGImageRef
et la place dans la variable contents
de la couche. Mais c'est animé et je ne le veux pas.
J'ai tout essayé:
removeAnimationForKey:
removeAllAnimations
delegate
[CATransaction setDisableAnimations:YES]
Cela semble correct. Je ne comprends pas pourquoi cette couche est toujours animée;
Est-ce que je fais quelque chose de mal? Y a-t-il un moyen secret?
Vous devez désactiver explicitement les animations en encapsulant votre code dans une transaction CATransaction.
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
layer.content = someImageRef;
[CATransaction commit];
Rapide
CATransaction.begin()
CATransaction.setDisableActions(true)
// change layer properties that you don't want to animate
CATransaction.commit()
À partir de Mac OS X 10.6 et iOS 3, CATransaction
dispose également d'une méthode setDisableActions
qui définit la valeur de la clé kCATransactionDisableActions
.
[CATransaction begin];
[CATransaction setDisableActions:YES];
layer.content = someImageRef;
[CATransaction commit];
Dans Swift, j'aime utiliser cette méthode d'extension:
extension CATransaction {
class func withDisabledActions<T>(_ body: () throws -> T) rethrows -> T {
CATransaction.begin()
CATransaction.setDisableActions(true)
defer {
CATransaction.commit()
}
return try body()
}
}
Vous pouvez ensuite l'utiliser comme ceci:
CATransaction.withDisabledActions {
// your stuff here
}
Autrement:
Vous devez désactiver l'animation par défaut de votre feuille.layer, qui est appelé implicitement lors de l'ajout d'une sous-couche.
Vous devriez également contenu-animation de chaque sous-couche. Bien sûr, vous pouvez utiliser "kCATransactionDisableActions" de CATransaction chaque fois que vous définissez sublayer.content. Mais, vous pouvez désactiver cette animation une fois, lorsque vous créez votre sous-couche.
Voici le code:
// 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.
/**
* 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()
}
Ajoutez ce code n'importe où dans votre code (portée globale)
Extension Swift 4:
extension CATransaction {
static func disableAnimations(_ completion: () -> Void) {
CATransaction.begin()
CATransaction.setDisableActions(true)
completion()
CATransaction.commit()
}
}
Utilisation:
CATransaction.disableAnimations {
// things you don't want to animate
}
Swift 2
J'ai pu désactiver toutes les animations comme suit, où myView
est la vue avec laquelle vous travaillez:
myView.layer.sublayers?.forEach { $0.removeAllAnimations() }
Et en guise de remarque, en supprimant toutes les couches:
myView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
avant en ajoutant le calque à votre vue avec [self.layer addSublayer:yourCALayer]
et après son ajout, vous pouvez désactiver des propriétés animées spécifiques de votre CALayer en écrasant la clé d’animation. La clé que vous définissez sur NULL est nommée d'après la propriété, affichée ici comme si elle était exécutée pour la fonction layer.position = CGPoint(x,y);
.
yourCALayer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"position"];
Comme la propriété actions
est un NSDictionary qui n'autorise pas le stockage de nil
, vous le définissez explicitement avec un objet NULL avec [NSNull null]
, identique à (id)kCFNull
. Vous pouvez le faire pour tous les sous-calques en effectuant une itération dans tous les sous-calques couche vues avec ...
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"]];
}
C'est une vieille question mais le problème demeure. Parfois, vous ne souhaitez pas que les animations que CALayer vous impose. Je n'étais pas satisfait de l'approche basée sur les transactions car je voulais simplement désactiver ces actions. Pour de bon. Voici une solution de Swift 4 à la sous-classe CALayer pour permettre le choix d’autoriser toute action ou de la désactiver globalement. Vous pouvez également créer des sous-classes CAShapeLayer, CATextLayer avec le même contenu:
public class ActionCALayer: CALayer {
public var allowActions: Bool = false
override public func action(forKey event: String) -> CAAction? {
return allowActions ? super.action(forKey: event) : nil
}
}