[Obj-C] Problème d'animation
Hello,
Voila je viens à vous car j'ai un petit souci niveau animation que je n'arrive pas à comprendre (et mes collègues non plus).
J'essaye de déplacer un bouton grace à une animation (et également passer en opacité 0 certains éléments), puis à la fin de cette animation je lance une seconde animation pour changer la taille de mon bouton, et retirer le titre du bouton.
Cette animation se fait en tant qu'IBAction sur le bouton que je souhaite bouger
Voila ma manière de faire :
[UIView animateWithDuration:2.0 animations:^{
self.firstThemeButton.frame = CGRectMake(self.view.center.x - self.firstThemeButton.frame.size.width / 2,
self.view.center.y - self.firstThemeButton.frame.size.height / 2,
self.firstThemeButton.frame.size.width,
self.firstThemeButton.frame.size.height);
self.titleLabel.alpha = 0;
self.descLabel.alpha = 0;
self.separatorView.alpha = 0;
self.logoImageView.alpha = 0;
self.arrowImageView.alpha = 0;
}];
[UIView animateWithDuration:0.5 delay:2.0 options:0 animations:^{
[self.firstThemeButton setTitle:@"" forState:UIControlStateNormal];
self.firstThemeButton.frame = CGRectMake(self.view.center.x - self.firstThemeButton.frame.size.width / 2,
self.view.center.y - self.firstThemeButton.frame.size.height / 2,
self.firstThemeButton.frame.size.width,
self.firstThemeButton.frame.size.height * 2);
} completion:nil];
Lors de mon 1er clic il me passe bien mes éléments en alpha 0 et il me retire bien mon titre sur le bouton.
Mais niveau animation, je vois disparaitre et s'afficher à sa position initiale (pas celle définie dans l'animation) et concernant sa taille elle ne change pas non plus.
En revanche si je clique une 2e fois, le bouton se met bien à la bonne position et se retaille bien.
Je ne pense pas que ça joue (puisque j'ai essayé en les retirant mais ça n'a rien changé) mais j'ai des contraintes sur ce bouton.
Merci aux âmes charitables qui me liront et qui m'aideront.
Bonne journée à tous.
Réponses
Si tu as mis les contraintes pour positionner le bouton, tu auras un conflit entre les contraintes et ton dimensionnement manuel.
Quand on enchaine les animations il est de bon ton de lancer la suivante dans le
completionBlock
de la précédente. Parce que rien ne peut t'assurer que :1. Ta première animation démarre tout de suite.
2. Ta deuxième animation démarre pile 2 secondes après.
Vu la manière dont CoreAnimation est construit ça peut poser un tas de soucis. Pour faire simple part toujours du principe que tout ce qui est asynchrone (animations, appels réseau, etc...) doit être considéré comme totalement détaché de ton main thread (en fait c'est clairement le cas).
Ce qui veut dire que tu peux écrire les functions dans l'ordre que tu veux rien ne t'assure que ça sera l'ordre d'exécution. À moins de synchroniser les appels grâce aux completion callbacks.
Je voudrais bien t'aider, mais il fait 37° ici et rien qu'en voyant ces [[]]] mon esprit a pris 10° en plus et provoqué une alerte de surchauffe..
Quant j'ai un problème du même genre, je crée une mini-application ne faisant que ça, une sorte de bac à sable pour bien isoler le dysfonctionnement. Cela m'aide à me concentrer sur l'essentiel et c'est plus facile à publier sur un forum qu'une poignée de ligne de codes alors que le problème peut venir d'ailleurs.
@Joanna Carter ça ne m'a pas posé de souci pour redimensionner mon bouton, ni le replacer.
@Pyroh j'ai essayé ça mais le résultat est toujours foireux, il fait l'animation pour bien se placer à la nouvelle position, mais à la fin de l'animation le bouton reprends sa place initiale (et le bouton ne change pas sa hauteur)
@Draken c'est mon 1er ViewController et il n'y a que ça dessus, donc ça viens forcément de la et pas d'ailleurs
Bah non, il n'y a pas que ça. Il manque les contraintes et le Storyboard.
Au lieu de jouer avec la
frame
essaie de manipuler plutôtcenter
etbounds
.Comme dit Draken, avec l'autolayout, il faut jouer avec les contraintes et pas le frame/bounds/width/height/etc.
Normalement oui mais il dit avoir testé avec et sans. D'où mon scepticisme...
Ben, on peut créer des outlets à partir des contraintes pour les animer.
Si tu utilises des contraintes, alors anime les contraintes. Change leurs valeurs.
De plus, il faut que tu mettes
[[self view] layoutIfNeeded];
à la fin des différents changements des contraintes.Pour info sur mon bouton j'ai ces contraintes la :
J'ai supprimer la dernière et ça ne solutionne pas mon souci de placement de bouton
Donc, animes les contraintes !
Si j'ai bien compris, ton bouton est centré horizontalement par rapport à la superView.
Ton bouton est aligné en hauteur pour être à la même hauteur (de manière centrée) que le Arrow Image.
Tu souhaites faire en sorte que ton bouton ailles au centre verticalement de la superView dans la première animation.
Tu as
Align Center Y to Arrow Image
, donc clairement, changer sa frame en y ne marchera pas.Puisque si c'est bien compris avec
self.view.center.y - self.firstThemeButton.frame.size.height / 2,
.Un truc simple à faire :
Dans Interface Builder :
Créer la première contrainte (que tu n'as pas déjà créé).
Lie les 2 IBOutlet.
Passe la propreté de
firstButtonAlignCenterYToSuperViewConstraint
à 250. (Low)Passe la propreté de
firstButtonAlignCenterYArrowConstraint
à 750. (High)Dans le block d'animation, juste fait :
Une fois que tu as compris comment faire, créé un
IBOutlet
pour la contrainte de width du bouton, et tu peux faire unlaConstrainte.constant = ??
@Larme même en faisant comme ça j'ai le même souci, de vue qui se place à sa position initiale
Bon ça a marché voila le code mis en place
Merci @Joanna Carter @Larme @Pyroh @Draken pour votre aide
Il y a un truc curieux dans ton code. Tu détruits DEUX contraintes au début de l'animation, pour n'en reconstruire qu'une seule juste après. C'est normal ?
Alors que tu tu les gardes, un activate/deactivate devrait être suffisant...
@Draken oui c'est normal, les 2 contraintes sont des contraintes sur des éléments que je passe en alpha 0 donc j'ai plus envie que les contraintes existent entre ces entités.
@Larme elles ne me sont plus utiles après donc autant les virer, tu crois pas ?
C'est risqué ça. Cela pourrais poser problème avec une future version d'iOS, si le moteur de contraintes devient plus .. contraignant exigeant que maintenant ! Par prudence tu devrais aussi désactiver ces entités avec isHidden (pour une réutilisation éventuelle) ou un removeFromSuperView().