J'ai une couche avec du code de dessin complexe dans sa méthode -drawInContext :. J'essaie de minimiser la quantité de dessin que je dois faire, donc j'utilise -setNeedsDisplayInRect: pour mettre à jour uniquement les pièces modifiées. Cela fonctionne à merveille. Cependant, lorsque le système graphique met à jour mon calque, il passe de l'ancienne à la nouvelle image en utilisant un fondu enchaîné. J'aimerais que cela change instantanément.
J'ai essayé d'utiliser CATransaction pour désactiver les actions et définir la durée sur zéro, et aucun des deux ne fonctionne. Voici le code que j'utilise:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
Y a-t-il une méthode différente sur CATransaction que je devrais utiliser à la place (j'ai également essayé -setValue: forKey: avec kCATransactionDisableActions, même résultat).
la source
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
Réponses:
Vous pouvez le faire en définissant le dictionnaire d'actions sur le calque pour qu'il renvoie
[NSNull null]
une animation pour la clé appropriée. Par exemple, j'utilisepour désactiver les animations de fondu entrant / sortant lors de l'insertion ou du changement de sous-couches dans l'un de mes calques, ainsi que des changements dans la taille et le contenu du calque. Je pense que la
contents
clé est celle que vous recherchez pour éviter le fondu enchaîné sur le dessin mis à jour.Version Swift:
la source
@"position"
clé.@"hidden"
propriété dans le dictionnaire d'actions si vous basculez la visibilité d'un calque de cette manière et souhaitez désactiver l'animation d'opacité.actionForKey:
place), découvrirfontSize
,contents
,onLayout
etbounds
. Il semble que vous puissiez spécifier n'importe quelle clé que vous pourriez utiliser dans lasetValue:forKey:
méthode, en spécifiant en fait des chemins de clés complexes commebounds.size
.Aussi:
la source
//foo
par[self setNeedsDisplayInRect: rect]; [self displayIfNeeded];
pour répondre à la question d'origine.[CATransaction setDisableActions:YES]
[CATransaction setDisableActions:YES]
est un raccourci pour juste la[CATransaction setValue:forKey:]
ligne. Vous avez toujours besoin des lignesbegin
etcommit
.Lorsque vous modifiez la propriété d'un calque, CA crée généralement un objet de transaction implicite pour animer la modification. Si vous ne souhaitez pas animer la modification, vous pouvez désactiver les animations implicites en créant une transaction explicite et en définissant sa propriété kCATransactionDisableActions sur true .
Objectif c
Rapide
la source
En plus de la réponse de Brad Larson : pour les couches personnalisées (que vous avez créées), vous pouvez utiliser la délégation au lieu de modifier le
actions
dictionnaire des couches . Cette approche est plus dynamique et peut être plus performante. Et il permet de désactiver toutes les animations implicites sans avoir à lister toutes les clés animables.Malheureusement, il est impossible d'utiliser les
UIView
s comme délégués de couche personnalisés, car chacunUIView
est déjà un délégué de sa propre couche. Mais vous pouvez utiliser une classe d'assistance simple comme celle-ci:Utilisation (à l'intérieur de la vue):
Parfois, il est pratique d'avoir le contrôleur de vue comme délégué pour les sous-couches personnalisées de vue; dans ce cas, il n'y a pas besoin d'une classe d'assistance, vous pouvez implémenter la
actionForLayer:forKey:
méthode directement dans le contrôleur.Note importante: n'essayez pas de modifier le délégué de
UIView
la couche sous-jacente (par exemple pour activer des animations implicites) - de mauvaises choses vont arriver :)Remarque: si vous souhaitez animer (et non désactiver l'animation pour) les redessins de calques, il est inutile de mettre un
[CALayer setNeedsDisplayInRect:]
appel à l'intérieur de aCATransaction
, car un redessinage réel peut (et se produira probablement) parfois plus tard. La bonne approche consiste à utiliser des propriétés personnalisées, comme décrit dans cette réponse .la source
CALayer
qui empêchaitnoImplicitAnimations
de travailler. Peut-être devriez-vous marquer votre propre réponse comme correcte et expliquer ce qui n'allait pas avec cette couche?CALayer
instance (j'en avais deux à l'époque).NSNull
n'implémente pas leCAAction
protocole et ce n'est pas un protocole qui n'a que des méthodes optionnelles. Ce code plante également et vous ne pouvez même pas le traduire rapidement. Meilleure solution: rendre votre objet conforme auCAAction
protocole (avec unerunActionForKey:object:arguments:
méthode vide qui ne fait rien) et renvoyer à laself
place de[NSNull null]
. Même effet mais sûr (ne plantera pas à coup sûr) et fonctionne également dans Swift.Voici une solution plus efficace, similaire à la réponse acceptée mais pour Swift . Dans certains cas, ce sera mieux que de créer une transaction à chaque fois que vous modifiez la valeur, ce qui est un problème de performance comme d'autres l'ont mentionné, par exemple, un cas d'utilisation courant consistant à faire glisser la position du calque à 60 ips.
Consultez la documentation d'Apple pour savoir comment les actions de calque sont résolues . La mise en œuvre du délégué sauterait un niveau de plus dans la cascade, mais dans mon cas, c'était trop compliqué en raison de la mise en garde concernant le délégué devant être défini sur l'UIView associé .
Edit: mis à jour grâce au commentateur soulignant que se
NSNull
conforme àCAAction
.la source
NullAction
pour Swift,NSNull
conforme àCAAction
déjà afin que vous puissiez faire la même chose que vous faites dans l'objectif C: layer.actions = ["position": NSNull ()]Sur la base de la réponse de Sam et des difficultés de Simon ... ajoutez la référence du délégué après avoir créé le CSShapeLayer:
... ailleurs dans le fichier "m" ...
Essentiellement le même que celui de Sam sans la possibilité de basculer via l'arrangement de variable personnalisé "disableImplicitAnimations". Plus d'une approche "hard-wire".
la source
En fait, je n'ai trouvé aucune des réponses comme étant la bonne. La méthode qui résout le problème pour moi était la suivante:
Ensuite, vous pouvez quelle que soit la logique qui s'y trouve, pour désactiver une animation spécifique, mais comme je voulais les supprimer toutes, j'ai renvoyé zéro.
la source
Pour désactiver les animations de calques implicites dans Swift
la source
disableActions()
car il semble que cela fasse la même chose, mais c'est en fait pour obtenir la valeur actuelle. Je pense que c'est marqué@discardable
aussi, ce qui rend cela plus difficile à repérer. Source: developer.apple.com/documentation/quartzcore/catransaction/...Découvrez une méthode plus simple pour désactiver l'action à l'intérieur d'un
CATransaction
qui appelle en internesetValue:forKey:
lakCATransactionDisableActions
clé:Rapide:
la source
Ajoutez ceci à votre classe personnalisée où vous implémentez la méthode -drawRect (). Apportez des modifications au code pour répondre à vos besoins, pour moi, l'opacité a fait l'affaire pour arrêter l'animation en fondu enchaîné.
la source
Si jamais vous avez besoin d'une solution très rapide (mais certes piratée), cela vaut peut-être la peine de le faire (Swift):
la source
view.layer?.actions = [:]
ça ne marche pas vraiment. Le réglage de la vitesse est moche mais fonctionne.Mise à jour pour accélérer et désactiver une seule animation de propriété implicite sous iOS et non sous MacOS
Autre exemple, dans ce cas, l'élimination de deux animations implicites.
la source
À partir d' iOS 7, il existe une méthode pratique qui fait exactement cela:
la source
Pour désactiver l'animation ennuyeuse (floue) lors de la modification de la propriété de chaîne d'un CATextLayer, vous pouvez le faire:
puis utilisez-le comme tel (n'oubliez pas de configurer correctement votre CATextLayer, par exemple la police correcte, etc.):
Vous pouvez voir ma configuration complète de CATextLayer ici:
Vous pouvez maintenant mettre à jour caTextLayer.string autant que vous le souhaitez =)
Inspiré par ceci et par cette réponse.
la source
Essaye ça.
avertissement
Si vous définissez le délégué de l'instance UITableView, il se produit parfois un crash (probablement le plus fort de scrollview appelé récursivement).
la source