102

I have the following CATransition for a UIView called finalScoreView, which makes it enter the screen from the top:

CATransition *animation = [CATransition animation];
animation.duration = 0.2;
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromBottom;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

[gameOver.layer addAnimation:animation forKey:@"changeTextTransition"];
[finalScoreView.layer addAnimation:animation forKey:@"changeTextTransition"];

How do I make it so it bounces once after it comes down, then stays still? It should still enter the screen from the top but then bounce when it comes down.

Any help would be much appreciated, thanks!

memmons
  • 40,222
  • 21
  • 149
  • 183
WunDaii
  • 2,322
  • 4
  • 18
  • 26

4 Answers4

273

A simpler alternative to UIDynamicAnimator in iOS 7 is Spring Animation (a new and powerful UIView block animation), which can give you nice bouncing effect with damping and velocity: Objective C

[UIView animateWithDuration:duration
  delay:delay
  usingSpringWithDamping:damping
  initialSpringVelocity:velocity
  options:options animations:^{
    //Animations
    }
  completion:^(BOOL finished) {
    //Completion Block
}];

Swift

UIView.animateWithDuration(duration,
     delay: delay,
     usingSpringWithDamping: damping,
     initialSpringVelocity: velocity,
     options: options,
     animations: {
            //Do all animations here
            }, completion: {
            //Code to run after animating
                (value: Bool) in
        })

Swift 4.0

UIView.animate(withDuration:duration,
     delay: delay,
     usingSpringWithDamping: damping,
     initialSpringVelocity: velocity,
     options: options,
     animations: {
            //Do all animations here
            }, completion: {
            //Code to run after animating
                (value: Bool) in
        })

usingSpringWithDamping 0.0 == very bouncy. 1.0 makes it smoothly decelerate without overshooting.

initialSpringVelocity is, roughly, "desired distance, divided by desired seconds". 1.0 corresponds to the total animation distance traversed in one second. Example, total animation distance is 200 points and you want the start of the animation to match a view velocity of 100 pt/s, use a value of 0.5.

More detailed tutorial and sample app can be found in this tutorial. I hope this is useful for someone.

Rohit Pathak
  • 359
  • 4
  • 16
huong
  • 4,534
  • 6
  • 33
  • 54
  • 3
    Here is a demo project I created to help you get the animation just right. Enjoy! https://github.com/jstnheo/SpringDampingDemo – jstn Dec 15 '15 at 00:14
  • Cheers for that demo project, mate. Really helps figure these values out since they are quite obtuse. I wish Apple had made them clearer – kakubei Dec 19 '18 at 11:16
  • My only problem with this is that it will go past the point I want it to go. At least when I'm animating the height – 12944qwerty Jul 13 '22 at 01:32
147

With iOS7 and UIKit Dynamics, there is no longer any need to use CAKeyframeAnimations or UIView animations!

Take a look at Apple's UIKit Dynamics Catalog app. Alternately, Teehanlax has a clear, concise tutorial with the full project in github. If you want a more detailed tutorial about the ins-and-outs of dynamics, the Ray Winderlich tutorial is great. As always, the Apple docs are a great first stop, so check out the UIDynamicAnimator Class reference in the docs.

Here's a bit of the code from the Teenhanlax tutorial:

self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

UIGravityBehavior *gravityBehavior = 
                [[UIGravityBehavior alloc] initWithItems:@[self.redSquare]];
[self.animator addBehavior:gravityBehavior];
    
UICollisionBehavior *collisionBehavior = 
                [[UICollisionBehavior alloc] initWithItems:@[self.redSquare]]; 
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collisionBehavior];
    
UIDynamicItemBehavior *elasticityBehavior = 
                [[UIDynamicItemBehavior alloc] initWithItems:@[self.redSquare]];
elasticityBehavior.elasticity = 0.7f;
[self.animator addBehavior:elasticityBehavior];

And here are the results

Square bounce

UIKit Dynamics is a really powerful and easy to use addition to iOS7 and you can get some great looking UI from it.

Other examples:

Button bounce

Slide bounce

Springy collection

WWDC spring collection

The steps to implement UIKit dynamics is always the same:

  1. Create a UIDynamicAnimator and store it in a strong property
  2. Create one or more UIDynamicBehaviors. Each behavior should have one or more items, typically a view to animate.
  3. Make sure that the initial state of the items used in the UIDynamicBehaviors is a valid state within the UIDynamicAnimator simulation.
Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
memmons
  • 40,222
  • 21
  • 149
  • 183
  • 1
    Hi Michael, thanks so much for your help! This definitely looks extremely easy to do! I tried it and it works when it hits the bottom of the view, but it doesn't work with another view - http://stackoverflow.com/questions/21895674/uidynamicanimator-wont-work-with-uiview-but-will-with-self-view - I would love if you could help me out there! :) Thanks – WunDaii Feb 20 '14 at 00:41
  • 2
    A MAGNIFICENT tutorial BUT you'd just use one line of code, usingSpringWithDamping, for a bounce ! – Fattie Jun 08 '14 at 17:27
  • 3
    Can you share some code sample for the Uitableview bounce animation as above. I am trying with UITableview but not sure from where to start. – Dinesh Nov 17 '16 at 08:44
  • 1
    UIKit Dynamics is great when you deal with example cases. But when it comes to real tasks, you see how raw and restricted is it. One big problem is overriding of `UIDynamicItemBehavior` (which is actually properties, not behavior). You can't just use different physical properties in different behaviors. Another case is implementing UIScrollView-like rubber bounds - it's very complicated. I can write even more but comment is too short. – kelin Feb 20 '17 at 03:19
  • 2
    add full code please. Your code describes how to create `UIDynamicAnimator` and objects associated with it but doesn't answer how to use them – Vyachaslav Gerchicov Jun 26 '17 at 10:50
  • Yes, I didn't find this answer helpful because it's too exploratory and doesn't focus on the desired task of simply adding bounce to a UIView. I'm not interested in finding out what I can do, but rather how to solve the specific problem. – Erika Electra Nov 09 '17 at 04:54
35

Here is a demo project I created to help you get the animation just right. Enjoy!

SpringDampingDemo

enter image description here

jstn
  • 1,862
  • 1
  • 13
  • 7
  • Cheers for that demo project, mate. Really helps figure these values out since they are quite obtuse. I wish Apple had made them clearer – kakubei Dec 19 '18 at 11:16
-1
- (IBAction)searchViewAction:(UIButton*)sender
{
  if(sender.tag == 0)
  {
    sender.tag = 1;

    CGRect optionsFrame2 = self.defaultTopView.frame;
    optionsFrame2.origin.x = -320;

    CGRect optionsFrame = self.searhTopView.frame;
    optionsFrame.origin.x = 320;
    self.searhTopView.frame = optionsFrame;

    [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:0 animations:^{

        CGRect optionsFrame = self.searhTopView.frame;

        optionsFrame.origin.x = 0;
        self.searhTopView.frame = optionsFrame;
        self.defaultTopView.frame = optionsFrame2;
    } completion:^(BOOL finished) {
    }];        
}
else
{
    sender.tag = 0;

    CGRect optionsFrame2 = self.defaultTopView.frame;
    optionsFrame2.origin.x = 0;

    CGRect optionsFrame = self.searhTopView.frame;
    optionsFrame.origin.x = 320;

    [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:0 animations:^{

        CGRect optionsFrame = self.searhTopView.frame;

        optionsFrame.origin.x = 320;
        self.searhTopView.frame = optionsFrame;
        self.defaultTopView.frame = optionsFrame2;
    } completion:^(BOOL finished) {
    }];
}
}
Community
  • 1
  • 1
Waseem Sarwar
  • 2,645
  • 1
  • 21
  • 18