Comment animer la contrainte des changements?
Je suis à jour d'une ancienne application avec un AdBannerView
et quand il n'y a pas d'annonce, il se glisse hors de l'écran. Quand il y a une annonce à ce qu'il glisse sur l'écran. Des trucs de base.
De style ancien, j'ai mis l'image dans un bloc d'animation.
Nouveau style, j'ai un IBOutlet
à l'auto-contrainte de mise en page qui détermine la position Y, dans ce cas, c'est la distance à partir du bas de la superview, et de modifier la constante:
- (void)moveBannerOffScreen {
[UIView animateWithDuration:5 animations:^{
_addBannerDistanceFromBottomConstraint.constant = -32;
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
[UIView animateWithDuration:5 animations:^{
_addBannerDistanceFromBottomConstraint.constant = 0;
}];
bannerIsVisible = TRUE;
}
Et la bannière se déplace, exactement comme prévu, mais pas animation.
Mise à JOUR: j'ai re-regardé La WWDC 12 parler les Meilleures Pratiques pour la maîtrise de la Mise en page Automatique qui couvre l'animation. Il explique comment mettre à jour les contraintes à l'aide de CoreAnimation:
J'ai essayé avec le code suivant, mais obtenir exactement les mêmes résultats:
- (void)moveBannerOffScreen {
_addBannerDistanceFromBottomConstraint.constant = -32;
[UIView animateWithDuration:2 animations:^{
[self.view setNeedsLayout];
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
_addBannerDistanceFromBottomConstraint.constant = 0;
[UIView animateWithDuration:2 animations:^{
[self.view setNeedsLayout];
}];
bannerIsVisible = TRUE;
}
Sur une note de côté, j'ai vérifié de nombreuses fois et c'est en cours d'exécution sur le principal fil.
- Je n'ai jamais vu autant de votes offert pour une question et une réponse sur une faute de frappe sur DONC, avant de
- Si il y a une faute de frappe dans la réponse, vous devez modifier la réponse. C'est pourquoi ils sont modifiables.
- Il serait plus utile si vous l'avez fait remarquer la faute de frappe, donc je savais où l'erreur a été. Vous pouvez modifier la réponse vous-même et fixe la typo de sauver tout le monde notre diatribe. Je n'ai juste le modifier pour supprimer la constante de l'animation de bloc, si c'est ce que vous faisiez référence à l'.
- Je ne sais pas ce que la typo est. J'ai été de répondre aux commentaires ci-dessus.
- Puis la typo est la question. Bêtement, j'ai été en tapant "setNeedsLayout" au lieu de "layoutIfNeeded". Il est clairement indiqué dans ma question, quand j'ai couper et coller mon code avec l'erreur et les captures d'écran avec le bon de commande. Encore n'arrivais pas à l'avis de til quelqu'un l'a fait remarquer.
Vous devez vous connecter pour publier un commentaire.
Deux remarques importantes:
Vous devez appeler
layoutIfNeeded
dans le bloc d'animation. Effectivement d'Apple vous recommande d'appeler une seule fois avant le bloc d'animation pour s'assurer que tous en attendant la mise en page des opérations ont été achevéesVous avez besoin d'appeler explicitement à la vue parent (par exemple
self.view
), pas à la vue enfant qui a des contraintes liées à elle. Cela permettra de mettre à jour tous contraint points de vue, y compris l'animation d'autres points de vue qui pourraient être limitée à la vue de la modification de la contrainte (par exemple, la Vue B est fixée à la partie inférieure de Vue et que vous venez de modifier la Vue du haut de décalage et que vous souhaitez Afficher B pour animer avec elle)Essayez ceci:
Objective-C
Swift 3
setNeedsLayout
au lieu delayoutIfNeeded
. Je suis un peu horrifiée par combien d'heures j'ai passé pas remarquer je viens juste trompé de nom de la méthode.UILabel
s. Certains type d'animation avec UILabel fonctionne différemment contre le même code avec un simple UIView . Malheureusement, je ne sais pas pourquoi. Et si quelqu'un sait à ce sujet, j'apprécie vraiment de commentaire moi.self.view.layoutIfNeeded()
dans le bloc d'animation, PAS la fin du bloc. Doh![subview.superview layoutIfNeeded];
layoutIfNeeded
puis le programme d'installation bloc d'animation avec une contrainte que vous souhaitez animer, un autrelayoutIfNeeded
inclus.J'apprécie la réponse, mais je pense qu'il serait bien de prendre un peu plus loin.
Le bloc de base de l'animation de la documentation
mais vraiment c'est un scénario très simpliste. Que faire si je veux animer sous-vue des contraintes via la
updateConstraints
méthode?Un bloc d'animation qui appelle la sous-vues updateConstraints méthode
La updateConstraints méthode est substituée dans la sous-classe UIView et doit appeler super à la fin de la méthode.
Le Guide De Mise En Page Automatique laisse beaucoup à désirer, mais il vaut la peine de lire. Je suis moi-même à l'aide de cette partie d'un
UISwitch
qui permet de basculer d'une sous-vue avec une paire deUITextField
s avec un simple et subtile de l'effondrement de l'animation (de 0,2 secondes). Les contraintes de la sous-vue sont gérés dans le UIView sous-classes updateConstraints méthodes décrites ci-dessus.self.view
(et pas sur une sous-vue de ce point de vue), l'appel deupdateConstraintsIfNeeded
n'est pas nécessaire (carsetNeedsLayout
déclenche égalementupdateConstraints
de ce point de vue). Peut-être anodin pour la plupart, mais il n'était pas pour moi jusqu'à maintenant 😉UIViewAnimationOptionBeginFromCurrentState
les contraintes de mise en forme sera mis en AVANT l'animation!Généralement, vous avez juste besoin de mettre à jour les contraintes et les appeler
layoutIfNeeded
à l'intérieur du bloc d'animation. Cela peut être soit la modification de la.constant
propriété d'unNSLayoutConstraint
, l'ajout de supprimer les contraintes (iOS 7), ou la modification de la.active
propriété de contraintes (iOS 8 & 9).Exemple De Code:
Exemple De Configuration:
Controverse
Il y a quelques questions quant à savoir si la contrainte doit être changé avant le bloc d'animation, ou à l'intérieur de (voir réponse à la question précédente).
Ce qui suit est une conversation sur Twitter entre Martin Pilkington qui enseigne iOS, et Ken Ferry qui a écrit Mise en page Automatique. Ken explique que s'évolution des constantes de l'extérieur du bloc d'animation peut actuellement de travail, il n'est pas sûr et qu'ils doivent être vraiment changer à l'intérieur de le bloc d'animation.
https://twitter.com/kongtomorrow/status/440627401018466305
Animation:
Exemple De Projet
Voici un projet simple qui montre comment un point de vue peut être animé. C'est en Objective C et anime la vue par la modification de la
.active
propriété de plusieurs contraintes.https://github.com/shepting/SampleAutoLayoutAnimation
Swift 4 solution
UIView.animer
Trois étapes simples:
Modifier les contraintes, par exemple:
Dire le contenant
view
que sa mise en page est sale et que la mise en page automatique doit recalculer la mise en page:Dans l'animation bloc-dire la mise en page pour recalculer la mise en page, qui est l'équivalent de fixer les images directement (dans ce cas, la mise en page automatique permettra de définir les cadres):
Complet exemple le plus simple:
Note
Il y a une option 0e étape avant de changer les contraintes que vous voudrez peut-être appeler
self.view.layoutIfNeeded()
pour s'assurer que le point de départ de l'animation est à partir de l'état avec les anciennes contraintes appliquées (en cas il y a d'autres contraintes changements ne devraient pas être inclus dans l'animation):UIViewPropertyAnimator
Depuis avec iOS 10 nous avons un nouveau animer le mécanisme de la
UIViewPropertyAnimator
, nous devrions savoir que, fondamentalement, le même mécanisme s'applique à elle. Les étapes sont fondamentalement les mêmes:Depuis
animator
est une encapsulation de l'animation, nous pouvons faire référence à elle et l'appeler plus tard. Toutefois, puisque dans le bloc d'animation, nous venons de dire de la mise en page automatique pour recalculer les images, nous devons changer les contraintes avant d'appelerstartAnimation
. Donc quelque chose comme ceci est possible:L'ordre de l'évolution des contraintes et de départ d'un animateur est important - si nous avons juste changé les contraintes et les laisser notre animateur pour un moment plus tard, le prochain dessin cycle peut invoquer la mise en page automatique de recalcul et le changement ne sera pas animé.
Aussi, n'oubliez pas qu'un simple animateur est non-réutilisable - une fois que vous l'exécutez, vous ne pouvez pas "réexécuter" il. Donc je suppose qu'il n'est pas vraiment une bonne raison de garder l'animateur autour de nous, à moins de l'utiliser pour contrôler une animation interactive.
Storyboard, du Code, des Conseils et quelques Astuces
Autres réponses sont très bien mais cela on met en évidence quelques-uns assez important pièges de l'animation de contraintes à l'aide d'un exemple récent. Je suis passé par beaucoup de variations avant, j'ai réalisé les opérations suivantes:
Rendre les contraintes que vous souhaitez cibler dans la Classe des variables pour stocker une référence forte. En Swift, j'ai utilisé paresseux variables:
Après quelques essais j'ai constaté que l'on DOIT obtenir la contrainte à partir de la vue ci-DESSUS (aka le superview) les deux points de vue où la contrainte est définie. Dans l'exemple ci-dessous (à la fois MNGStarRating et UIWebView sont les deux types d'éléments, je suis entrain de créer une contrainte entre les deux, et ils sont des sous-vues à l'intérieur de soi.la vue).
Filtre Chaînage
Je profite de Swift méthode de filtre pour séparer le désiré contrainte qui servira de point d'inflexion. On pourrait aussi obtenir beaucoup plus compliqué, mais le filtre ne un bon travail ici.
Animer Les Contraintes De L'Utilisation De Swift
En supposant que vous créez une propriété de filtre avec des critères exacts et obtenir à un point d'inflexion pour votre animation (bien sûr vous pouvez également filtrer un tableau et une boucle dans si vous avez besoin de plusieurs contraintes):
....
Quelque temps plus tard...
Le nombre de tours de mal
Ces notes sont vraiment un ensemble de conseils que j'ai écrit pour moi-même. J'ai fait toutes les choses à ne pas faire personnellement et douloureusement. J'espère que ce guide peut vous épargner d'autres.
Regarder pour z-positionnement. Parfois, quand rien n'est apparemment
qui se passe, vous devriez vous cacher certains des autres points de vue ou de l'utilisation de la vue
débogueur pour localiser votre vue animée. J'ai même trouvé des cas où un Utilisateur Défini Runtime
Attribut a été perdu dans un storyboard du xml et a conduit à l'animation
vue d'être recouverts (tout en travaillant).
Toujours prendre une minute pour lire la documentation (anciens et nouveaux), Rapide
De l'aide, et les en-têtes. Apple continue de faire beaucoup de changements pour mieux
gérer la mise en page automatique des contraintes (voir la pile de vues). Ou au moins le Mise En Page Automatique Livre De Recettes. Gardez à l'esprit que, parfois, les meilleures solutions sont dans les anciens documents/vidéos.
Jouer avec les valeurs de l'animation et envisager l'utilisation d'
d'autres animateWithDuration variantes.
Ne pas coder en dur la mise en page spécifique de valeurs comme critères pour déterminer
modifications à d'autres constantes, au lieu d'utiliser les valeurs qui vous permettent de
déterminer l'emplacement de la vue.
CGRectContainsRect
est unexemple
une vue de participer à la définition de la contrainte
let viewMargins = self.webview.layoutMarginsGuide
: est sur exemplestoryboard ont des contraintes attachées à la propriété
auto.viewName.les contraintes
mine de 250 (faible) ou 750 (haut) sur la table de montage séquentiel; (si vous essayez de modifier un 1000 priorité à rien dans le code de l'application va se planter, car 1000 est nécessaire)
deactivateConstraints (ils ont leur place, mais quand il vient à l'apprentissage ou si vous utilisez une table de montage à l'aide de ces signifie probablement que vous faites trop de ~ ils ne sont même si, comme vu ci-dessous)
vraiment ajouter une nouvelle contrainte dans le code. J'ai trouvé que la plupart du temps je
mise en page les points de vue dans la table de montage avec des contraintes fixées (en plaçant
l'affichage à l'écran), puis dans le code, j'anime les contraintes précédemment créé dans la table de montage séquentiel pour déplacer le point de vue.
NSAnchorLayout classe et sous-classes. Celles-ci fonctionnent très bien, mais il
m'a fallu un moment pour réaliser que toutes les contraintes que j'avais besoin
il existait déjà dans la table de montage séquentiel. Si vous construisez des contraintes dans le code
puis très certainement utiliser cette méthode pour agréger vos contraintes:
Échantillon rapide De Solutions pour les ÉVITER lors de l'utilisation des story-boards
Si vous oubliez l'un de ces conseils ou les plus simples, telles que l'endroit où ajouter le layoutIfNeeded, la plus probable, il ne se passera rien: Dans ce cas, vous pouvez avoir un mi cuit de solution comme ceci:
Extrait du Guide de mise en page automatique (notez le deuxième extrait de l'aide de mac OS X). BTW - Ce n'est plus dans le guide actuel aussi loin que je peux voir. Les techniques préférées continuer à évoluer.
Animer les Modifications Apportées par la Mise en page Automatique
Si vous avez besoin d'un contrôle complet sur l'animation des modifications apportées par la Mise en page Automatique, vous devez faire votre contrainte des changements de programme. Le concept de base est le même pour les deux iOS et OS X, mais il ya quelques différences mineures.
Dans une application iOS, votre code devrait ressembler à quelque chose comme ce qui suit:
Dans OS X, utilisez le code suivant lors de l'utilisation de la couche adossés à des animations:
Quand vous n'êtes pas en utilisant la couche adossés à des animations, vous devez animer la constante à l'aide de la contrainte de l'animateur:
Pour ceux qui apprennent mieux visuellement découvrez ce début de vidéo d'Apple.
Attention
Souvent dans la documentation il y a des petites notes, ou des morceaux de code qui conduisent à de plus grandes idées. Par exemple fixation auto contraintes de mise en forme dynamique d'animateurs est une grande idée.
Bonne Chance et que la Force soit avec vous.Solution Swift:
Solution De Travail De 100% Swift 3.1
j'ai lu toutes les réponses et que vous souhaitez partager du code et de la hiérarchie de lignes que j'ai utilisé dans toutes mes applications pour animer correctement, Certaines solutions ne fonctionnent pas, vous devez les vérifier sur des périphériques lents.e.g un iPhone 5 en ce moment.
J'étais en train d'animer des Contraintes et n'était pas vraiment facile de trouver une bonne explication.
Ce que d'autres réponses sont en train de dire est tout à fait vrai: vous devez appeler
[self.view layoutIfNeeded];
à l'intérieur deanimateWithDuration: animations:
. Cependant, l'autre point important est d'avoir des pointeurs pour chaqueNSLayoutConstraint
que vous souhaitez animer.J'ai créé un exemple sur GitHub.
De travail et viens de tester la solution pour Swift 3 avec Xcode 8.3.3:
Il suffit de garder à l'esprit que soi.calendarViewHeight est une contrainte visée à l'un customView (CalendarView). J'ai appelé le .layoutIfNeeded() sur l'auto.vue et PAS sur de soi.calendarView
Espérons que cette aide.
Il y a un article à ce sujet:
http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was
Dans lequel, il a codé comme ceci:
Espère que cela aide.
Dans le contexte de la contrainte de l'animation, je voudrais mentionner une situation particulière où j'ai animé une contrainte immédiatement dans un keyboard_opened de notification.
Contrainte défini un supérieur de l'espace à partir d'un champ texte pour le récipient. Sur le clavier de l'ouverture, je viens de diviser la constante par 2.
J'ai été incapable de parvenir à un conistent lisse contrainte d'animation directement dans le clavier de notification. Environ la moitié du temps de point de vue, juste sauter sa nouvelle position - sans animation.
Elle s'est produite pour moi il y a peut être quelques autres layouting passe comme résultat de clavier d'ouverture.
L'ajout d'une simple dispatch_after bloc avec un retard de 10 ms fait de l'animation d'exécuter à chaque fois, pas de saut.
Pour les autres Xamarians, voici les Xamarin.iOS/C# version: