constraint animations animate ios swift xcode6 uiviewanimation

ios - animations - Cómo animar una UIView con restricciones en Swift?



uiview animation swift 4 (5)

En mi ejemplo artificial, tengo la siguiente vista única:

Como puede ver, se compone de algunas restricciones simples:

  1. Alinea los centros horizontales y verticales,
  2. Altura (establecida en una constante)
  3. Líder y espacios finales (establecidos en constante)

Lo que estoy tratando de lograr es tener esta visión rojiza / rosada "entrar" desde arriba. Tradicionalmente, en un mundo sin restricciones, simplemente modificaría el marco dentro de UIView.animateWithDuration , sin embargo, no estoy seguro de cómo hago lo similar en un mundo restringido.

Para reiterar mi pregunta, ¿cómo puedo hacer que mi vista comience fuera de la escena y animar la vista desde la parte superior?

Consideré animar la restricción de centros verticales (y luego llamar a layoutIfNeeded ), pero no está logrando el efecto deseado.

Gracias por tu ayuda.


Lo que desea es, de hecho, bastante simple, y detallaré cómo se debe hacer sin interferir con las prioridades o las constantes funky. De esta forma podemos obtener una animación que funcionará en cualquier tamaño de pantalla.

El TL; DR es que necesita configurar sus restricciones y luego llama a layoutIfNeeded dentro de su bloque de animación para animar los cambios. Para más información, vea esta publicación SO .

Entonces, necesitamos dos conjuntos de restricciones para ocultar y mostrar la vista. En viewDidLoad la vista se viewDidLoad , y luego en viewDidAppear o donde quiera que la vista se deslice.

Configuración de Storyboard / XIB

Entonces, lo primero es configurar las restricciones que no cambiarán en IB (o código, con el que se sienta cómodo). A saber; la altura de la vista roja y su espacio inicial y posterior al contenedor. Por lo tanto, sus restricciones podrían verse así ( nota: no he establecido una restricción de ancho sino que los espacios iniciales y finales definen el ancho):

Ahora verá que IB le advertirá que no hay ninguna restricción configurada para la posición Y de su vista (de ahí las líneas de puntos rojas)

Ahora puede agregar el espacio superior a la restricción del contenedor y establecerlo como una restricción de marcador de posición (casilla de verificación que dice "eliminar en tiempo de compilación"). Hacemos esto porque queremos controlar dónde está la vista programáticamente.

Esto significa que esta restricción no existirá una vez que se carga la vista, pero sirve para eliminar todas sus advertencias cuando le está diciendo a IB que usted sabe cómo manejar esta restricción cuando se carga la vista.

Tiempo de codificación

Ahora necesitamos un método para ocultar la vista, un método para mostrar la vista. Para esto vamos a almacenar la restricción de posicionamiento Y en la vista y luego animarla. Nuestro viewController podría verse así:

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

Ocultación

Nuestro método para ocultar la vista simplemente puede eliminar la restricción de posición y luego agregar una con la parte inferior de las vistas rojas igual a la vista superior del controlador de vista:

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

Demostración

De manera similar, nuestra restricción show moverá el centro Y de la vista al centro Y de los controladores:

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étodos de conveniencia

Para completar, los métodos de conveniencia que he usado se ven así:

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

También puede verificar si la vista roja es visible usando algunas matemáticas CGRect:

func isRedViewVisible() -> Bool { return CGRectContainsPoint(self.view.bounds, self.redView.frame.origin) }


Lo que puede hacer es agregar el siguiente código en su método viewDidAppear . En primer lugar, IBOutlet una propiedad IBOutlet de la restricción Y del centro de su vista y luego cambia su valor constante.

self.centerYConstraint.constant = 500.0 self.view.layoutIfNeeded() UIView.animateWithDuration(Double(0.5), animations: { self.centerYConstraint.constant = 0 self.view.layoutIfNeeded() })


Para cualquiera que busque animación simple como la solicitud:

Para la animación de deslizamiento, debe usar [...] CGAffineTransformMakeTranslation (x, y) .

La razón es que para una animación de deslizamiento, primero debe mover la vista de la pantalla y luego llevarla a su posición original. Entonces en tu viewDidLoad simplemente usa:

yourView.transform = CGAffineTransformMakeTranslation(0, 500)

Esto mueve la vista fuera de la pantalla, en este caso en la parte inferior. Ahora en viewDidAppear puedes mostrar tu vista con:

UIView.animateWithDuration(0.7, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: [], animations: { self.yourView.transform = CGAffineTransformMakeScale(1, 1) }, completion: nil)

Con estas líneas puede agregar las restricciones que desee en su UIView y colocarlas donde necesite en su ViewController.


Para mí, la mejor manera de animar Swift 3 y 4

self.constraint.constant = -150 UIView.animate(withDuration: 0.45) { [weak self] in self?.view.layoutIfNeeded() }


Prueba esto:

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

Tenga cuidado con el firstItem y el secondItem orden de elementos en la restricción. El código anterior supone que Superview es el firstItem :

Otra forma es definir dos restricciones:

  • Restricción de alineación de centro Y (Superview.CenterY == View.CenterY) priority = 750
  • Restricción de espacio vertical (SuperView.Top == View.Bottom) priority = 500

Y ajuste la prioridad para determinar qué restricción debe ser adoptada.

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