Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stopping UIImageView animation gradually and smoothly

I have the following simple UIImageView animation:

-(void) setupTheAnimation {
  self.imgView.animationImages = imagesArr;
  [self.imgView setAnimationRepeatCount:-1];
  self.imgView.animationDuration =0.9;
  [self.imgView startAnimating];
  [self performSelector:@selector(stopTheAnimation) withObject:nil afterDelay:4.0];
}

-(void) stopTheAnimation {
  [self.imgView stopAnimating];
}

but I face a problem when the animation stops I do not know what is the last frame it stops at !! so the ending of animation is not smooth at all.

so I need to:

1) know what is the last frame at which the animation ends, so I set it as the last image of the animation and this leads to a smooth stopping.

2) stop this animation gradually, i.e. changing its duration time before it stops to slow it down first then stop it.

This is a link to the sample project.

like image 860
JAHelia Avatar asked Feb 18 '13 13:02

JAHelia


1 Answers

I know your original implementation uses animationImages, but I don't know of a way to use animationImages directly with a continuously variable duration. However, this is a pretty simple feature to implement yourself. If you do so, then you can code a dynamic duration value between images in your array.

In the following code, I replace animationImages with a custom stepping function, and dynamically adjust the duration after a stop has been requested. Take note that this is a little different than your original code, that specified a hard end time. This code specifies when the gear spin should start slowing down.

If you really have a hard animation period, you can adjust the call to stopTheAnimation to account for the deceleration factor you choose (I simply increase the duration by 10% per step, during deceleration, until the steps are slower than a given threshold value):

// my animation stops when the step duration reaches this value:
#define STOP_THRESHOLD_SECONDS 0.1f
#define NUM_IMAGES 35

@implementation ViewController
{
    NSMutableArray *imagesArr;
    int currentImage;
    BOOL stopRequested;
    NSTimeInterval duration;
}

-(void) setupTheAnimation {

    stopRequested = NO;
    currentImage = 0;
    duration = 0.9f / NUM_IMAGES;
    [self stepThroughImages];

    [self performSelector:@selector(stopTheAnimation) withObject:nil afterDelay:4.0];
}

- (void) stepThroughImages {

    self.imgView.image = [imagesArr objectAtIndex: currentImage];

    if (currentImage == NUM_IMAGES - 1) {
        currentImage = 0;
    } else {
        currentImage++;
    }

    if (stopRequested && duration < STOP_THRESHOLD_SECONDS) {
        // we're slowing down gradually
        duration *= 1.1f;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [self stepThroughImages];
        });
    } else if (!stopRequested) {
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [self stepThroughImages];
        });
    }
}

-(void) stopTheAnimation {
    stopRequested = YES;
}
like image 92
Nate Avatar answered Nov 18 '22 05:11

Nate