Mimic UIAlertView Bounce?

前端 未结 4 1869
面向向阳花
面向向阳花 2020-12-23 02:15

Whats the best way to mimic the bouncing animation from the UIAlertView on the iPhone? Is there some built-in mechanism for this? The UIAlertView itself won\'t work for my n

相关标签:
4条回答
  • 2020-12-23 02:56

    UIAlertView uses a more sophisticated animation:

    • scale to larger than 100%
    • scale to smaller than 100%
    • scale to 100%

    Here's an implementation using a CAKeyFrameAnimation:

    view.alpha = 0;
    [UIView animateWithDuration:0.1 animations:^{view.alpha = 1.0;}];
    
    CAKeyframeAnimation *bounceAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
    bounceAnimation.values = @[@0.01f, @1.1f, @0.8f, @1.0f];
    bounceAnimation.keyTimes = @[@0.0f, @0.5f, @0.75f, @1.0f];
    bounceAnimation.duration = 0.4;
    [view.layer addAnimation:bounceAnimation forKey:@"bounce"];
    
    0 讨论(0)
  • 2020-12-23 02:59

    You can use 2 animations, one to pop up to very large, and the other one to rescale back to normal size.

    (This is the approach use by UIAlertView internally.)

    Alternatively, you can use the lower-level CAAnimation and use +[CAMediaTimingFunction functionWithControlPoints::::] to make your own curve.

    0 讨论(0)
  • 2020-12-23 03:04

    I investigated how animations are added to UIAlertView's layer by swizzling -[CALayer addAnimation:forKey:]. Here are the values I got for the scale transform animations it performs:

    0.01f -> 1.10f -> 0.90f -> 1.00f

    with durations

    0.2s, 0.1s, 0.1s.

    All the animations use an ease in/ease out timing function. Here is a CAKeyframeAnimation that encapsulates this logic:

    CAKeyframeAnimation *bounceAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    bounceAnimation.fillMode = kCAFillModeBoth;
    bounceAnimation.removedOnCompletion = YES;
    bounceAnimation.duration = 0.4;
    bounceAnimation.values = @[
        [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.01f, 0.01f, 0.01f)],
        [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1f, 1.1f, 1.1f)],
        [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.9f, 0.9f, 0.9f)],
        [NSValue valueWithCATransform3D:CATransform3DIdentity]];
    bounceAnimation.keyTimes = @[@0.0f, @0.5f, @0.75f, @1.0f];
    bounceAnimation.timingFunctions = @[
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    

    I believe UIAlertView also performs a simple opacity animation from 0.0f to 1.0f over the total duration of the transform animation (0.4).

    0 讨论(0)
  • 2020-12-23 03:06

    Here's how I did it for an app I'm working on. The effect I was going for was bouncing when you pressed the view. Experiment with the values to suit your taste and the desired speed of the effect.

    - (void) bounceView:(UIView*)bouncer
    {
        // set duration to whatever you want
        float duration = 1.25;
        // use a consistent frame rate for smooth animation.
        // experiment to your taste
        float numSteps = 15 * duration;
    
        // scale the image up and down, halving the distance each time
        [UIView animateKeyframesWithDuration:duration
                                       delay:0
                                     options:UIViewKeyframeAnimationOptionCalculationModeCubic
                                  animations:^{
                                      float minScale = 0.50f; // minimum amount of shrink
                                      float maxScale = 1.75f; // maximum amount of grow
                                      for(int i = 0; i< numSteps*2; i+=2)
                                      {
                                          // bounce down
                                          [UIView addKeyframeWithRelativeStartTime:duration/numSteps * i
                                                                  relativeDuration:duration/numSteps
                                                                        animations:^{
                                                                            bouncer.layer.transform = CATransform3DMakeScale(minScale, minScale, 1);
                                                                        }];
                                          // bounce up
                                          [UIView addKeyframeWithRelativeStartTime:duration/numSteps * (i+1)
                                                                  relativeDuration:duration/numSteps
                                                                        animations:^{
                                                                            bouncer.layer.transform = CATransform3DMakeScale(maxScale, maxScale, 1);
                                                                        }];
    
                                          // cut min scale halfway to identity
                                          minScale = minScale + (1.0f - minScale) / 2.0f;
                                          // cut max scale halfway to identity
                                          maxScale = 1.0f + (maxScale - 1.0f) / 2.0f;
                                      }
                                  } completion:^(BOOL finished) {
                                      // quickly smooth out any rounding errors
                                      [UIView animateWithDuration:0.5*duration/numSteps animations:^{
                                          bouncer.layer.transform = CATransform3DIdentity;
                                      }];
                                  }];
    }
    
    0 讨论(0)
提交回复
热议问题