How can I have a handler for repeating UIView animateWithDuration?

I am using the UIView class's animateWithDuration method to repeat the animation of my view. How can I get a handler that can be used to stop this animation later? For example, a re-animation starts with one method and I need to stop it later from another method.

+2


source to share


4 answers


You could do something like this, assuming you created an overridden property. As noted in the comments, triggering a startup completion block. The animation call needs to be wrapped in an asynchronous call to avoid. Be sure to replace "id" with whatever class type you have.



- (void)startAnimation {
    [UIView animateWithDuration:1.0
                          delay:0.0
                        options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
                     animations:^(void) {
                         //animate
                     }
                     completion:^(BOOL finished) {
                         if(!self.canceled) {
                             __weak id weakSelf = self;
                             [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                 [weakSelf startAnimation];
                             }];
                         }
                     }
     ];
}

      

+8


source


The purpose of animation is to repeatedly animate the bounce of the image. When not worrying about manually stopping, you just need to set three properties (UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat)

and an animation block to move the image - self.image.center = CGPointMake(self.image.center.x, self.image.center.y+25);

Here is the complete animation code:

[UIView animateWithDuration:0.5 delay:0 options:( UIViewAnimationOptionCurveEaseIn | 
 UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | 
 UIViewAnimationOptionAllowUserInteraction) animations:^{self.image.center = 
 CGPointMake(self.image.center.x, self.image.center.y+25);} completion:nil];

      

What is it. But if you require manual control, then an additional code is required. First, according to jaminguy, you need to have a BOOL property to indicate the loop / stop (self.playAnimationForImage) animation, and clean up a separate method with animation code to be called from elsewhere. Here's the way:

-(void)animateImageBounce{
 [UIView animateWithDuration:0.5 delay:0 options:( 
  UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAutoreverse |  
  UIViewAnimationOptionAllowUserInteraction) animations:^{self.image.center = 
  CGPointMake(self.image.center.x, self.image.center.y+25);} completion:^(BOOL finished){if 
  (finished && self.playAnimationForImage){
    self.image.center = CGPointMake(self.image.center.x, self.image.center.y-25); 
    [self animateImageBounce];
  }}]; 

      



and here is the start of calling animation from some method

-(void)someMethod{
...
self.playAnimationForFingers = YES;
[self animateImageBounce];

      

}

What I would like to point out is that with manual control, you need to reset the center.y of the image back right before making the next recursive call.

+8


source


Actually the solution with recursive call didn't work for me. The animation started to behave strangely: every 2-3 cycles of animation repetition, I got animation breaks. After the first bounce of the part (moving the object down), the second part (upward movement) performed almost instantly. I believe it has something to do with the recursive call.

So I refused to use that. The solution was to start the animation with auto-reverse and repeat options, and in a full block check if the flag ( self.playAnimationForFingers

) indicates to stop the animation.

-(void)animateFingersForLevelCompleteScreen{
  //fix: reset the place of bouncing fingers (starting place). 
  //Otherwise the fingers will slowly move to the bottom at every level. 
  //This resetting is not working when placed inside UIView 
  //animate complete event block

  self.image.center = CGPointMake(10 + self.image.frame.size.width/2, 
                                  95 + self.image.frame.size.height/2); 

  [UIView animateWithDuration:0.5 delay:0 
    options:(UIViewAnimationOptionCurveEaseIn | 
             UIViewAnimationOptionAutoreverse | 
             UIViewAnimationOptionRepeat |
             UIViewAnimationOptionAllowUserInteraction) 
    animations:^{
      self.image.center = CGPointMake(self.image.center.x, 
                                      self.image.center.y+25);
    } 
    completion:^(BOOL finished){
      /*finished not approapriate: finished will not be TRUE if animation 
      was interrupted. It is very likely to happen because animation repeats && */
      if (!self.playAnimationForFingers){
         [UIView setAnimationRepeatAutoreverses:NO]; 
      }
  }];
}

      

+3


source


U can use CABasicAnimation.

    CABasicAnimation *appDeleteShakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
appDeleteShakeAnimation.autoreverses = YES;
appDeleteShakeAnimation.repeatDuration = HUGE_VALF;
appDeleteShakeAnimation.duration = 0.2;
appDeleteShakeAnimation.fromValue = [NSNumber numberWithFloat:-degreeToRadian(5)];
appDeleteShakeAnimation.toValue=[NSNumber numberWithFloat:degreeToRadian(5)];
[self.layer addAnimation:appDeleteShakeAnimation forKey:@"appDeleteShakeAnimation"];

      

Then when u wants to stop it you can just call

[self.layer removeAnimationForKey:@"appDeleteShakeAnimation"];

      

0


source







All Articles