Autolayout, UIDynamics y animaciones

Soy bastante nuevo en layout automático y estoy confundido acerca de cómo animar vistas.

Leí mucho, y sé que debes aferrarte a las restricciones, editarlo y envolver el layoutIfNeeded en un bloque de animation UIView .

Pero cuando se trata de hacerlo, estoy un poco perdido. Me encantaría que alguien me explicara cómo se hace esta animation, por ejemplo.

Creo que probablemente use un UIPanGestureRecognizer para cambiar la constant del espacio principal a la restricción del contenedor, pero probablemente use UIDynamics (para el efecto de rebote a la derecha).

Bueno, se podría lograr un comportamiento similar con UIPanGestureRecognizer + [UIView animateWithDuration:animations:] . Sí, establece la restricción de espacio principal y la cambia según el estado UIPanGestureRecognizer . Recuerde que necesita establecer restricciones finales solamente (defina la position final de un control deslizante). Las posiciones intermedias de animation se calculan para ti. Para el control deslizante tenemos la position izquierda pnetworkingeterminada y la position central activada .

Para la rotation de la vista podemos usar la propiedad transform de UIView .

Restricciones de autoajuste en IB:

Restricciones de reproducción automática en IB

Configurar opciones de animation ( UIViewAnimationOptionCurveEaseOut Curva de animation) podría dar una sensación de efecto de rebote. Código UIPanGestureRecognizer (omita la statement de variables de instancia, porque sus nombres son auto explicativos):

 - (IBAction)onPan:(UIPanGestureRecognizer*)sender { switch (sender.state) { case UIGestureRecognizerStateBegan: _startOffset = self.leadingSpace.constant; _maxOffset = self.slider.superview.frame.size.width - kHorizontalPadding - self.slider.frame.size.width; break; case UIGestureRecognizerStateChanged: { CGFloat offset = _startOffset + [sender translationInView:self.slider.superview].x; offset = MIN(offset, _maxOffset); self.leadingSpace.constant = offset; break; } case UIGestureRecognizerStateEnded: { CGFloat offset = _startOffset + [sender translationInView:sender.view.superview].x; UIColor *bgColor = [UIColor lightGrayColor]; CGFloat rotation = 0; if (offset < _maxOffset) { offset = kHorizontalPadding; } else { offset = (_maxOffset + kHorizontalPadding)/2; bgColor = [UIColor networkingColor]; rotation = M_PI_2; } self.leadingSpace.constant = offset; [UIView animateWithDuration:.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ [self.slider layoutIfNeeded]; self.slider.backgroundColor = bgColor; self.slider.transform = CGAffineTransformMakeRotation(rotation); } completion:nil]; break; } default: break; } } 

Resultado de animation con UIViewAnimationOptionCurveLinear (simulador de captura):

Resultado de la animación

Resultado de animation con UIViewAnimationOptionCurveEaseOut (simulador de captura):

Resultado de la animación

UIDynamics

Con UIDynamics las cosas se vuelven más complicadas. Buen punto de partida es el tutorial Ray Wenderlich UIKit Dynamics .

Para deslizar el control deslizante podríamos agregar los siguientes comportamientos:

  • UIGravityBehavior que tira de un control deslizante para iniciar la position. Necesitamos cambiar la propiedad de angle para dirigir la fuerza de gravedad hacia la izquierda.
  • UICollisionBehavior que define los bordes izquierdo y derecho de los movimientos permitidos. traduceReferenceBoundsIntoBoundary será útil si tratamos la vista padre como límite. También necesitamos agregar límites adicionales para detener el control deslizante en el medio utilizando addBoundaryWithIdentifier:fromPoint:toPoint (o la ruta bezier).
  • UIDynamicItemBehavior para cambiar las elasticy y posiblemente de resistance para configurar el rebote y la aceleración, respectivamente.
  • Posiblemente UIPushBehavior junto con UIPushBehavior 's velocityInView: para especificar la velocidad del slider cuando un usuario suelta un control deslizante
  • Posiblemente UISnapBehavior como una alternativa a UIGravityBehavior