Comment animer une uivi avec des contraintes dans Swift?
dans mon exemple artificiel, j'ai la vue unique suivante:
Comme vous pouvez le voir, il se compose de quelques contraintes:
- aligner les centres horizontaux et verticaux,
- Hauteur (définie à une constante près)
- attaque et de fuite des espaces (constante)
ce que je cherche à accomplir est de ayez cette vue rougeâtre / rosâtre "entrer" du haut. Traditionnellement, dans un monde sans contrainte , je modifierais simplement le cadre à l'intérieur de UIView.animateWithDuration
, mais je ne suis pas sûr de savoir comment je fais le similaire dans un monde de contrainte.
pour réitérer ma question, Comment puis-je faire démarrer ma vue hors de la scène et animer la vue en venant du haut?
j'ai envisagé d'animer la contrainte des centres verticaux (et d'appeler ensuite layoutIfNeeded
), mais il n'atteint pas l'effet désiré.
Merci pour votre aide.
5 réponses
ce que vous pouvez faire est d'ajouter le code suivant dans votre méthode viewDidAppear
. Vous faites d'abord une propriété IBOutlet
de la contrainte y centrale de votre vue, puis vous changez sa valeur constante.
self.centerYConstraint.constant = 500.0
self.view.layoutIfNeeded()
UIView.animateWithDuration(Double(0.5), animations: {
self.centerYConstraint.constant = 0
self.view.layoutIfNeeded()
})
ce que vous voulez est en fait assez simple, et je vais détailler comment cela devrait être fait sans toucher aux priorités ou aux constantes funky. De cette façon, nous pouvons obtenir une animation qui fonctionnera sur n'importe quelle taille d'écran.
Le TL;DR, c'est que vous avez besoin pour configurer vos contraintes et ensuite appeler layoutIfNeeded à l'intérieur de votre bloc d'animation pour animer les modifications. Pour plus de voir ce So post .
nous avons donc besoin de deux séries de contraintes pour se cacher et montrer la vue. Dans viewDidLoad
la vue sera cachée, et puis dans viewDidAppear
ou où nous voulons que cette vue glisse.
table de montage séquentiel/XIB Setup
donc la première chose à faire est de configurer les contraintes qui ne changeront pas en IB (ou code, selon ce qui vous convient). À savoir: la hauteur de la vue rouge, et son espace de tête et de fuite vers le conteneur. Ainsi, vos contraintes pourraient ressembler à ceci ( note: Je n'ai pas défini de contrainte de largeur, mais laisser les espaces avant et arrière définir la largeur):
maintenant vous verrez que IB vous avertira qu'il n'y a pas de contrainte configurée pour la position Y de votre vue (d'où les lignes pointillées rouges)
vous pouvez maintenant ajouter l'espace supérieur à la contrainte de conteneur et le Définir comme un placeholder contrainte (case à cocher "Supprimer au moment de la compilation"). Nous le faisons parce que nous voulons contrôler où la vue est programmatique.
cela signifie que cette contrainte n'existera pas une fois la vue chargée mais servira à supprimer tous vos Avertissements car vous dites à IB que vous savez comment gérer cette contrainte lorsque la vue est chargée.
Temps De Codage
maintenant nous avons besoin d'un méthode pour masquer la vue, une méthode pour montrer le point de vue. Pour cela nous allons stocker la contrainte de positionnement Y sur la vue et ensuite l'animer. Notre viewController pourrait ressembler à ceci:
@IBOutlet weak var redView: UIView!
var redViewYPositionConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
self.hideRedViewAnimated(false)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.showRedViewAnimated(true)
}
se cacher
notre méthode pour masquer la vue peut simplement supprimer la contrainte de position et en ajouter une avec les vues rouges en bas égale à la vue du contrôleur de vue en haut:
func hideRedViewAnimated(animated: Bool) {
//remove current constraint
self.removeRedViewYPositionConstraint()
let hideConstraint = NSLayoutConstraint(item: self.redView,
attribute: .Bottom,
relatedBy: .Equal,
toItem: self.view,
attribute: .Top,
multiplier: 1,
constant: 0)
self.redViewYPositionConstraint = hideConstraint
self.view.addConstraint(hideConstraint)
//animate changes
self.performConstraintLayout(animated: animated)
}
montrant
De la même façon, notre contrainte show déplacera le centre de la vue Y vers le centre des contrôleurs Y:
func showRedViewAnimated(animated: Bool) {
//remove current constraint
self.removeRedViewYPositionConstraint()
let centerYConstraint = NSLayoutConstraint(item: self.redView,
attribute: .CenterY,
relatedBy: .Equal,
toItem: self.view,
attribute: .CenterY,
multiplier: 1,
constant: 0)
self.redViewYPositionConstraint = centerYConstraint
self.view.addConstraint(centerYConstraint)
//animate changes
self.performConstraintLayout(animated: animated)
}
Méthodes Pratiques
Pour l'intégralité de la commodité méthodes que j'ai utilisé ressembler à ceci:
func performConstraintLayout(animated animated: Bool) {
if animated == true {
UIView.animateWithDuration(1,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 0.6,
options: .BeginFromCurrentState,
animations: { () -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
} else {
self.view.layoutIfNeeded()
}
}
func removeRedViewYPositionConstraint() {
if redViewYPositionConstraint != nil {
self.view.removeConstraint(self.redViewYPositionConstraint!)
self.redViewYPositionConstraint = nil
}
}
vous pouvez également vérifier si la vue Rouge est visible en utilisant quelques mathématiques de CGRect:
func isRedViewVisible() -> Bool {
return CGRectContainsPoint(self.view.bounds, self.redView.frame.origin)
}
essayez ceci:
class ViewController: UIViewController {
// red view
@IBOutlet weak var myView: UIView!
// vertical align contraint
@IBOutlet weak var verticalConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
verticalConstraint.constant = (myView.bounds.height + self.view.bounds.height)/2
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5) {
self.verticalConstraint.constant = 0
self.view.layoutIfNeeded()
}
}
}
attention à l'ordre firstItem
et secondItem
dans la contrainte. Le code ci-dessus suppose Superview est le firstItem
:
autre façon est de définir deux contraintes:
- Centre O Alignement de la contrainte (Superview.CenterY == Vue.Priorité = 750
- Espace Vertical Contrainte (SuperView.Haut = = Vue.En bas) priorité = 500
et ajuster la priorité afin de déterminer la contre-mesure à adopter.
class ViewController: UIViewController {
// vertical align contraint
@IBOutlet weak var centerYConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
centerYConstraint.priority = 250
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5) {
self.centerYConstraint.priority = 750
self.view.layoutIfNeeded()
}
}
}
pour toute personne à la recherche d'une simple animation comme la demande:
pour l'animation slide up que vous devez utiliser [...] le Gcaffinetransformmaketranslation (x, y) .
la raison est que pour une animation slide up vous devez d'abord déplacer le vue de l'écran et puis le ramener à sa position initiale. Donc, en votre viewDidLoad juste utiliser:
yourView.transform = CGAffineTransformMakeTranslation(0, 500)
cela déplace le vue hors de l'écran, dans ce cas, à la partie inférieure. Maintenant, dans le viewDidAppear vous pouvez montrer votre point de vue:
UIView.animateWithDuration(0.7, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: [], animations: { self.yourView.transform = CGAffineTransformMakeScale(1, 1) }, completion: nil)
avec ces lignes, vous pouvez ajouter les contraintes que vous voulez sur votre uivi et les placer là où vous avez besoin dans votre ViewController.
pour moi la meilleure façon pour animer Swift 3 & 4
self.constraint.constant = -150
UIView.animate(withDuration: 0.45) { [weak self] in
self?.view.layoutIfNeeded()
}