Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate Auto Layout backed view using UIKitDynamics

I'd like to use a UIKitDynamics UISnapBehaviour to spice up the animation (appearance + position change on rotation) of a button that itself is positioned in a view using Auto Layout.

I understand that while applying UIKitDynamics forces I need to disable auto-layout constraints from the button temporarily. I am thinking of the following process …

  1. Get the target center/bounds of the button before the Auto Layout based transition happens (but after it is triggered). Save that value.
  2. Temporarily disable all Auto Layout/constraints of the button
  3. Apply the UISnapBehaviour. Feed it with the saved target center or bounds value from Auto Layout (from step 1).
  4. When the UIKitDynamics animation is finished re-enable the constraints to prepare for any further layout change

Is this the right approach?

Which delegate/layout should be used for those those respective steps + how do I get the target center of a view from Auto Layout before the actual Auto Layout based animation/transition happens?

like image 604
Bernd Avatar asked Oct 09 '14 06:10

Bernd


1 Answers

I might suggest a different approach that approximates the UISnapBehavior, but avoids trying to marry UIKit Dynamics with an auto layout where you are relying upon the auto layout engine to determine the final position of the view. (Obviously, if you knew the final destination, then you'd just suspend auto layout, snap, and when the snap was done, you'd then apply the constraints.)

For the bouncing effect as the view snaps into place, you can use animateWithDuration with usingSpringWithDamping parameter, e.g.:

// create the view

UIView *view = ...;
view.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view];

// add all of the constraints for the final position

NSDictionary *views = NSDictionaryOfVariableBindings(view);
[self.view addConstraints:...];

// animate the application of those constraints with low `withSpringWithDamping`

[UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.0 options:0 animations:^{
    [view layoutIfNeeded];
} completion:nil];

If you also want some rotation as it snaps into place, you can use animateKeyframesWithDuration:

[UIView animateKeyframesWithDuration:1.0 delay:0.0 options:0 animations:^{
    [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
        view.transform = CGAffineTransformMakeRotation(M_PI_4 / 2);
    }];
    [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
        view.transform = CGAffineTransformMakeRotation(-M_PI_4 / 4);
    }];
    [UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.125 animations:^{
        view.transform = CGAffineTransformMakeRotation(M_PI_4 / 16);
    }];
    [UIView addKeyframeWithRelativeStartTime:0.875 relativeDuration:0.125 animations:^{
        view.transform = CGAffineTransformMakeRotation(0);
    }];
} completion:nil];

This isn't precisely the UISnapBehavior, but approximates it pretty closely. You can play around with the timing and amount of rotations in the key frame animation as well as the spring damping factor, too. But this illustrates one approach to get snap-like behavior using block-based animation.

like image 125
Rob Avatar answered Nov 01 '22 23:11

Rob