UIView Infinite 360 degree rotation animation? UIView Infinite 360 degree rotation animation? ios ios

UIView Infinite 360 degree rotation animation?


Found a method (I modified it a bit) that worked perfectly for me: iphone UIImageView rotation

#import <QuartzCore/QuartzCore.h>- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations:(CGFloat)rotations repeat:(float)repeat {    CABasicAnimation* rotationAnimation;    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];    rotationAnimation.duration = duration;    rotationAnimation.cumulative = YES;    rotationAnimation.repeatCount = repeat ? HUGE_VALF : 0;    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];}


Kudos to Richard J. Ross III for the idea, but I found that his code wasn't quite what I needed. The default for options, I believe, is to give you UIViewAnimationOptionCurveEaseInOut, which doesn't look right in a continuous animation. Also, I added a check so that I could stop my animation at an even quarter turn if I needed (not infinite, but of indefinite duration), and made the acceleration ramp up during the first 90 degrees, and decelerate during the last 90 degrees (after a stop has been requested):

// an ivar for your class:BOOL animating;- (void)spinWithOptions:(UIViewAnimationOptions)options {   // this spin completes 360 degrees every 2 seconds   [UIView animateWithDuration:0.5                         delay:0                       options:options                    animations:^{                       self.imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);                    }                    completion:^(BOOL finished) {                       if (finished) {                          if (animating) {                             // if flag still set, keep spinning with constant speed                             [self spinWithOptions: UIViewAnimationOptionCurveLinear];                          } else if (options != UIViewAnimationOptionCurveEaseOut) {                             // one last spin, with deceleration                             [self spinWithOptions: UIViewAnimationOptionCurveEaseOut];                          }                       }                    }];}- (void)startSpin {   if (!animating) {      animating = YES;      [self spinWithOptions: UIViewAnimationOptionCurveEaseIn];   }}- (void)stopSpin {    // set the flag to stop spinning after one last 90 degree increment    animating = NO;}

Update

I added the ability to handle requests to start spinning again (startSpin), while the previous spin is winding down (completing). Sample project here on Github.


In Swift, you can use the following code for infinite rotation:

Swift 4

extension UIView {    private static let kRotationAnimationKey = "rotationanimationkey"    func rotate(duration: Double = 1) {        if layer.animation(forKey: UIView.kRotationAnimationKey) == nil {            let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")            rotationAnimation.fromValue = 0.0            rotationAnimation.toValue = Float.pi * 2.0            rotationAnimation.duration = duration            rotationAnimation.repeatCount = Float.infinity            layer.add(rotationAnimation, forKey: UIView.kRotationAnimationKey)        }    }    func stopRotating() {        if layer.animation(forKey: UIView.kRotationAnimationKey) != nil {            layer.removeAnimation(forKey: UIView.kRotationAnimationKey)        }    }}

Swift 3

let kRotationAnimationKey = "com.myapplication.rotationanimationkey" // Any keyfunc rotateView(view: UIView, duration: Double = 1) {    if view.layer.animationForKey(kRotationAnimationKey) == nil {        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")        rotationAnimation.fromValue = 0.0        rotationAnimation.toValue = Float(M_PI * 2.0)        rotationAnimation.duration = duration        rotationAnimation.repeatCount = Float.infinity        view.layer.addAnimation(rotationAnimation, forKey: kRotationAnimationKey)    }}

Stopping is like:

func stopRotatingView(view: UIView) {    if view.layer.animationForKey(kRotationAnimationKey) != nil {        view.layer.removeAnimationForKey(kRotationAnimationKey)    }}