Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chain UIView animations with time intervals

I need to animate 3 UIViews (fade in/out). 1 animation duration is 0.6s (fade in/out cycle is 0.6+0.6s). But I need to launch animations in 0.2 seconds.

  • 1st animation should be launched in 0.0 seconds.
  • 2nd animation should be launched in 0.2 seconds.
  • 3rd animation should be launched in 0.4 seconds.

And all of them should be looped "indefinitely" (until some trigger).

What I have at the moment:

- (void)playAnimation {
    isAnimated = YES;
    [self animateView:firstView afterDelay:0.0];
    [self animateView:secondView afterDelay:0.2];
    [self animateView:thirdView afterDelay:0.4];
}

- (void)stopAnimation {
    isAnimated = NO;
}

- (void)animateView:(UIView *)animatedView afterDelay:(float)delay {
    if(isAnimated) {
        [UIView animateWithDuration:0.6 delay:delay options:UIViewAnimationOptionTransitionNone
                     animations:^ {
            animatedView.alpha = 1.0;
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.6 animations:^ {
                animatedView.alpha = 0.0;
            } completion:^(BOOL finished) {
                [self animateView:animatedView afterDelay:0.0];
            }];
        }];
    }
}

This code works unpredictable. Sometimes view animation works like I want (with phase 0.2 seconds), some times it starts in the same time... What will be the proper way to do that? I've also tried to remove afterDelay: part from method signature and launch animateView method like that with exactly same effect:

[self performSelector:@selector(animateView:) withObject:thirdView afterDelay:0.6];

UPDATE
I've noticed that animation "breaks" when heavy networking stuff is performing in background (loading big images using AFNetworking). I don't mind if animation will "freeze" a bit (though I prefer to not have delays at all) but I really want to keep phases of all animations linked (with same phase difference).

To make problem easier to understand I've added graphs. Y is alpha, X is time. Top 3 graphs - what I want to have. Bottom ones - what I currently have. Highlighted area is where problem comes. You can see that second view's animation freeze for 0.2 seconds and synchronise with 3rd one. So they start blinking in the same phase. This is just one example. Some times they can animate ok, sometimes all 3 views "syncronize" in few rounds of animation and blink in same phase... Animation

like image 679
OgreSwamp Avatar asked May 27 '13 11:05

OgreSwamp


2 Answers

Looks like you want the same animation, applied to all 3 views, offset by t=0.2. You can use Core Animation to do exactly what you want with very little effort.

Doing it this way they will always be timed correctly.

I propose this:

-(void)playAnimation
{
    CABasicAnimation * anim = [ CABasicAnimation animationWithKeyPath:@"opacity" ] ;
    anim.autoreverses = YES ;
    anim.repeatCount = CGFLOAT_MAX ;
    anim.removedOnCompletion = NO ;
    anim.duration = 0.6 ;
    anim.fromValue = @0.0 ;
    anim.toValue = @1.0;

    // finish configuring your animation here (timing function, speed, duration, fill mode, etc) ...

    CFTimeInterval t = CACurrentMediaTime() ;

    anim.beginTime = t ;
    [ self.firstView.layer addAnimation:anim forKey:@"opacity-anim" ] ; // name is so you can remove this anim later

    anim.beginTime += 0.2 ;
    [ self.secondView.layer addAnimation:anim forKey:@"opacity-anim" ] ;

    anim.beginTime += 0.2 ;
    [ self.thirdView.layer addAnimation:anim forKey:@"opacity-anim" ] ; // name is so you can remove this anim later
}

-(void)stopAnimation
{
    [ self.firstView.layer removeAnimationForKey:@"opacity-anim" ] ;
    [ self.secondView.layer removeAnimationForKey:@"opacity-anim" ] ;
    [ self.thirdView.layer removeAnimationForKey:@"opacity-anim" ] ;
}

edit: oops! forgot the start, end values!

like image 124
nielsbot Avatar answered Nov 15 '22 09:11

nielsbot


The way to schedule animations properly is by using the CAMediaTiming protocol that the CAKeyframeAnimation class conforms to. See my answer below for links to resources on how to achieve this.

Changing speed of an ongoing CAKeyframeAnimation animation

like image 25
Max MacLeod Avatar answered Nov 15 '22 09:11

Max MacLeod