J'essaie d'animer certaines vues pour qu'elles soient bloquées par le clavier géant en mode paysage. Cela fonctionne bien si j'anime simplement les cadres, mais d'autres ont suggéré que c'était contre-productif et que je devrais plutôt mettre à jour NSLayoutConstraints. Cependant, ils ne semblent pas pouvoir être animés. Est-ce que quelqu'un les a obligés à travailler avec succès?
//heightFromTop is an NSLayoutConstraint referenced from IB
[UIView animateWithDuration:0.25 animations:^{
self.heightFromTop.constant= 550.f;
}];
Le résultat est un saut instantané à la hauteur en question.
Il suffit de suivre ce modèle exact:
self.heightFromTop.constant = 550.0f;
[myView setNeedsUpdateConstraints];
[UIView animateWithDuration:0.25f animations:^{
[myView layoutIfNeeded];
}];
où myView
est la vue où self.heightFromTop
a été ajouté à. Votre vue est "en train de" sauter car la seule chose que vous avez faite dans le bloc d'animation a été de définir la contrainte, ce qui ne provoque pas immédiatement de dispositions. Dans votre code, la présentation se produit lors de la prochaine boucle d'exécution après avoir défini heightFromTop.constant
et vous êtes déjà hors de portée du bloc d’animation.
Dans Swift 2:
self.heightFromTop.constant = 550
myView.setNeedsUpdateConstraints()
UIView.animateWithDuration(0.25, animations: {
myView.layoutIfNeeded()
})
La méthode suggérée par Apple est légèrement différente ( Voir l'exemple dans la section "Animation des modifications apportées par la disposition automatique" ). Vous devez d'abord appeler layoutIfNeeded avant l'animation. Ajoutez ensuite vos éléments d'animation à l'intérieur du bloc d'animation, puis appelez à nouveau layoutIfNeeded à la fin. Pour les gars comme moi qui sont en train de passer à l'autolayout, c'est plus similaire aux animations précédentes que nous faisions avec les images à l'intérieur de blocs d'animation. Nous avons juste besoin d'appeler layoutIfNeeded deux fois - avant les animations et après les animations:
[self.view layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0f animations:^{
// Make all constraint changes here
self.heightFromTop.constant= 550.f;
[self.view layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];
J'ai essayé l'approche de @ Centurion, mais ma vue s'animerait sur une mauvaise image si elle est chargée à partir du storyboard. Le problème disparaît si je remplace le premier layoutIfNeeded
par updateConstraintsIfNeeded
, bien que je ne sache pas pourquoi. Si quelqu'un peut donner une explication, ce serait très apprécié.
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0 animations:^{
self.myConstraint.constant= 100;
[self.view layoutIfNeeded];
}];
J'avais un problème similaire et ce fil était d'une grande aide pour le surmonter.
La réponse de erurainon m'a mis sur la bonne voie, mais j'aimerais proposer une réponse légèrement différente. Le code proposé par erurainon ne fonctionnait pas pour moi, car j'avais toujours un saut au lieu d'une transition animée. Le lien fourni par cnotethegr8 m'a donné la réponse de travail:
Guide de mise en page automatique https://developer.Apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample .html (jusqu'en bas de la page).
Quelques différences avec la réponse de erurainon:
Cela sera conforme au modèle suggéré par Apple dans le lien ci-dessus.
Un exemple
Je voulais animer une vue particulière en la fermant ou en l'agrandissant d'un simple clic. Étant donné que j'utilise autolayout et que je ne souhaite coder aucune dimension (dans le cas de ma hauteur) dans le code, j'ai décidé de capturer la hauteur dans viewDidLayoutSubviews. Vous devez utiliser cette méthode et non viewWillAppear lorsque vous utilisez autolayout. Comme viewDidLayoutSubviews peut être appelé plusieurs fois, j'ai utilisé un BOOL pour me tenir au courant de la première exécution de mon initialisation.
// Code snippets
@property (weak, nonatomic) IBOutlet UIView *topView; // Container for minimalView
@property (weak, nonatomic) IBOutlet UIView *minimalView; // View to animate
@property (nonatomic) CGFloat minimalViewFullHeight; // Original height of minimalView
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *minimalViewHeightConstraint;
@property (nonatomic) BOOL executedViewDidLayoutSubviews;
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// First execution of viewDidLayoutSubviews?
if(!self.executedViewDidLayoutSubviews){
self.executedViewDidLayoutSubviews = YES;
// Record some original dimensions
self.minimalViewFullHeight = self.minimalView.bounds.size.height;
// Setup our initial view configuration & let system know that
// constraints need to be updated.
self.minimalViewHeightConstraint.constant = 0.0;
[self.minimalView setNeedsUpdateConstraints];
[self.topView layoutIfNeeded];
}
}
Redimensionner l'extrait d'action complet
// An action to close our minimal view and show our normal (full) view
- (IBAction)resizeFullAction:(UIButton *)sender {
[self.topView layoutIfNeeded];
[UIView transitionWithView:self.minimalView
duration:1.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.minimalViewHeightConstraint.constant = 0.0;
// Following call to setNeedsUpdateConstraints may not be necessary
[self.minimalView setNeedsUpdateConstraints];
[self.topView layoutIfNeeded];
} completion:^(BOOL finished) {
;
}];
// Other code to show full view
// ...
}
Redimensionner le fragment d'action
// An action to open our minimal view and hide our normal (full) view
- (IBAction)resizeSmallAction:(UIButton *)sender {
[self.topView layoutIfNeeded];
[UIView transitionWithView:self.minimalView
duration:1.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.minimalViewHeightConstraint.constant = self.minimalViewFullHeight;
[self.minimalView setNeedsUpdateConstraints];
[self.topView layoutIfNeeded];
} completion:^(BOOL finished) {
;
}];
// Other code to hide full view
// ...
}
Vous pouvez utiliser animateWithDuration au lieu de transitionWithView si vous le souhaitez.
J'espère que cela t'aides.