Comment animer une uivi avec des contraintes dans Swift?

dans mon exemple artificiel, j'ai la vue unique suivante:

enter image description here

Comme vous pouvez le voir, il se compose de quelques contraintes:

  1. aligner les centres horizontaux et verticaux,
  2. Hauteur (définie à une constante près)
  3. 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.

38
demandé sur Daniel Galasko 2014-12-09 08:18:19

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()
    })
62
répondu gabbler 2014-12-09 06:04:21

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):

Constraints

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)

View with warnings

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.

enter image description here

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)
}
12
répondu Daniel Galasko 2017-05-23 12:09:55

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 :

screenshot


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

screenshot

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()
        }
    }

}
9
répondu rintaro 2014-12-09 06:42:14

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.

6
répondu Massimo Polimeni 2018-02-23 07:51:02

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()
}
0
répondu YannickSteph 2017-10-06 19:49:15