Chain UIView animations with time intervals

Deadly 提交于 2019-12-03 06:36:48

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!

Max MacLeod

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

Try instead of performSelector: the following sample

- (void)animateView:(UIView *)animatedView afterDelay:(float)delay {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        if(isAnimated) {
            [UIView animateWithDuration:0.6 delay:0.0 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];
                }];
            }];
        }
    });
}

Hope it will work as what you want.

- (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 delay:delay options:UIViewAnimationOptionTransitionNone animations:^{
                                  animatedView.alpha = 0.0;
                             } completion:^(BOOL finished) {
                                 [self animateView:animatedView afterDelay:delay];
                             }];
                         }];
    }
}

This is just some modification of your code.

Try this, this might work for you.

- (void)playAnimation {
    isAnimated = YES;

    [self performSelector:@selector(animateView:) withObject:firstView afterDelay:0.1];
    [self performSelector:@selector(animateView:) withObject:secondView afterDelay:0.2];
    [self performSelector:@selector(animateView:) withObject:thirdView afterDelay:0.4];
}


- (void)animateView:(UIView *)animatedView {
   //Here "animatedView" will contain (firstView/secondView/thirdView) whatever you are passing
   //your animation
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!