Autolayout, UIDynamics and animations

animation, autolayout, ios, uikit-dynamics

Solution

Well, similar behavior could be achieved with `UIPanGestureRecognizer` + `[UIView animateWithDuration:animations:]`. Yes, you set leading space constraint and change it according to `UIPanGestureRecognizer` state. Remember that you need to set final constraints only (define final position of a slider). Intermediate animation positions are calculated for you. For the slider we have default left position and activated middle position.

For view rotation we can use `transform` property of `UIView`.

Autolayout constraints in IB:

Setting animation options (`UIViewAnimationOptionCurveEaseOut` animation curve) could give a feel of bounce effect. `UIPanGestureRecognizer` code (omit instance variables declaration, because their names are self-explanatory):

- (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 redColor];
                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;
    }
}

Animation result with `UIViewAnimationOptionCurveLinear` (capture simulator):

Animation result with `UIViewAnimationOptionCurveEaseOut` (capture simulator):

UIDynamics

With UIDynamics things become more complicated. Good starting point is Ray Wenderlich UIKit Dynamics Tutorial.

For bouncing slider we could add following behaviors:

- `UIGravityBehavior` which pulls a slider to start position. We need to change `angle` property to direct gravity force to the left.

- `UICollisionBehavior` which defines left and right edges of allowed movements. `translatesReferenceBoundsIntoBoundary` property will be useful if we treat parent view as boundary. Also we need to add extra boundary to stop slider in the middle using `addBoundaryWithIdentifier:fromPoint:toPoint` (or bezier path).

- `UIDynamicItemBehavior` to change `elasticy` and possibly `resistance` properties to configure bounce and acceleration respectively.

- Possibly `UIPushBehavior` in conjunction with recognizer's `velocityInView:` to specify slider velocity when a user releases a slider

- Possibly `UISnapBehavior` as an alternative to `UIGravityBehavior`

Problem

I'm pretty new to auto layout and I'm confused about how to animate views. I read a lot, and I know you must hold to the constraints, edit it, and wrap the `layoutIfNeeded` in an `UIView` animation block. But when it comes to do it, I'm a little lost. I'd love if someone could explain me how this animation is done for example. I think it probably uses a `UIPanGestureRecognizer` to change the `constant` of the leading space to container constraint, but it probably uses UIDynamics (for the bounce effect at the right ?).

Original source