Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make UIView animation sequence repeat and autoreverse

How to make this complex animation repeat and autoreverse? Is there any way to add options UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat to this animation sequence?

   [UIView animateWithDuration:1.0f animations:^{          someView.frame = someFrame1;      } completion:^(BOOL finished) {          [UIView animateWithDuration:0.5f animations:^{              someView.frame = someFrame2;          } completion:nil];      }]; 
like image 556
B.S. Avatar asked Feb 06 '13 13:02

B.S.


People also ask

Does UIView animate need weak self?

You don't need to use [weak self] in static function UIView. animate() You need to use weak when retain cycle is possible and animations block is not retained by self.

Does UIView animate run on the main thread?

The contents of your block are performed on the main thread regardless of where you call [UIView animateWithDuration:animations:] . It's best to let the OS run your animations; the animation thread does not block the main thread -- only the animation block itself.

Is UIView animate asynchronous?

UIView. animate runs on the main thread and is asynchronous.


2 Answers

To animation from point 1 to 2 to 3 to 2 to 1 and repeat, you can do use animateKeyframesWithDuration in iOS 7 and later:

someView.frame = frame1; [UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat animations:^{     [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{         someView.frame = frame2;     }];     [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{         someView.frame = frame3;     }]; } completion:nil]; 

If using auto-layout, you can animate the changing of the constraint constants:

[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat animations:^{     [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{         topConstraint.constant = 200;         leftConstraint.constant = 200;         [self.view layoutIfNeeded];     }];     [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{         topConstraint.constant = 100;         leftConstraint.constant = 300;         [self.view layoutIfNeeded];     }]; } completion:nil]; 

Or, the approach with auto layout is to deactivate the constraints, and then you can animate using frame values or what have you.


In earlier versions of iOS, you can use CAKeyframeAnimation, for example to animate along a path:

UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(100.0, 100.0)]; [path addLineToPoint:CGPointMake(200.0, 200.0)]; [path addLineToPoint:CGPointMake(100.0, 300.0)];  CAKeyframeAnimation *animatePosition = [CAKeyframeAnimation animationWithKeyPath:@"position"]; animatePosition.path = [path CGPath]; animatePosition.duration = 1.0; animatePosition.autoreverses = YES; animatePosition.repeatCount = HUGE_VALF; [self.someView.layer addAnimation:animatePosition forKey:@"position"]; 

You can do this with however many points you want. This also useful technique if you want to animate along a curved path (e.g. a circle or bezier curve).


To just animate between two points, you can use animateWithDuration:delay:options:animations:completion:, such as:

[UIView animateWithDuration:0.5                       delay:0.0                     options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut                  animations:^{                      // do whatever animation you want, e.g.,                       someView.frame = someFrame1;                  }                  completion:NULL]; 

This animates the movement of someView from the starting frame to someFrame1 and back.

By the way, using UIViewAnimationOptionCurveEaseInOut in conjunction with UIViewAnimationOptionAutoreverse and UIViewAnimationOptionRepeat will give you a smoother effect as the animation reverses and repeats.

like image 158
Rob Avatar answered Sep 23 '22 21:09

Rob


Swift 4 for simple wiggle sequence:

func animateWiggle() {     // Set animation props     let scaleDelta = CGFloat(0.10)      // Set transforms     let wiggleOutHorizontally = CGAffineTransform(scaleX: 1.0 + scaleDelta, y: 1.0)     let wiggleOutVertically = CGAffineTransform(scaleX: 1.0, y: 1.0 + scaleDelta)      // Run animation sequence     UIView.animateKeyframes(withDuration: 1.0, delay: 0.0, options: [.autoreverse, .repeat], animations: {         // Animate wiggle horizontally         UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.5, animations: {             self.transform = wiggleOutHorizontally         })          // Animate wiggle vertically         UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: {             self.transform = wiggleOutVertically         })     },     completion: nil) } 
like image 20
Crashalot Avatar answered Sep 22 '22 21:09

Crashalot