9

我需要为 3 个 UIView 设置动画(淡入/淡出)。1个动画时长为0.6s(淡入淡出周期为0.6+0.6s)。但我需要在 0.2 秒内启动动画。

  • 第一个动画应该在 0.0 秒内启动。
  • 第二个动画应该在 0.2 秒内启动。
  • 第三个动画应该在 0.4 秒内启动。

并且所有这些都应该“无限期地”循环(直到某个触发)。

我目前拥有的:

- (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];
            }];
        }];
    }
}

此代码的工作方式不可预测。有时查看动画会像我想要的那样工作(阶段 0.2 秒),有时它会在同一时间开始......这样做的正确方法是什么?我还尝试afterDelay:从方法签名中删除部分并启动 animateView 方法,效果完全相同:

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

更新
我注意到当繁重的网络内容在后台执行时动画“中断”(使用 AFNetworking 加载大图像)。我不介意动画是否会“冻结”一点(尽管我更喜欢根本没有延迟),但我真的想保持所有动画的阶段链接(具有相同的相位差)。

为了让问题更容易理解,我添加了图表。Y 是 alpha,X 是时间。前 3 个图表 - 我想要的。底部的 - 我目前拥有的。突出显示的区域是问题出现的地方。您可以看到第二个视图的动画冻结 0.2 秒并与第三个同步。所以他们开始在同一阶段闪烁。这只是一个例子。有时他们可以制作动画,有时所有 3 个视图在几轮动画中“同步”并在同一阶段闪烁...... 动画

4

5 回答 5

10

看起来你想要相同的动画,应用于所有 3 个视图,偏移 t=0.2。您可以使用 Core Animation 轻松完成您想要的工作。

这样做,他们将始终正确计时。

我提出这个:

-(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" ] ;
}

编辑:哎呀!忘记了开始,结束的价值观!

于 2013-06-06T16:09:58.100 回答
1

正确安排动画的方法是使用类遵循的CAMediaTiming协议。CAKeyframeAnimation有关如何实现此目的的资源链接,请参见下面的答案。

改变正在进行的 CAKeyframeAnimation 动画的速度

于 2013-06-06T15:19:06.833 回答
0

希望它会像你想要的那样工作。

- (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];
                             }];
                         }];
    }
}

这只是对您的代码的一些修改。

于 2013-06-06T15:54:40.683 回答
0

尝试代替 performSelector:以下示例

- (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];
                }];
            }];
        }
    });
}
于 2013-05-27T13:55:20.377 回答
-2

试试这个,这可能对你有用。

- (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
}
于 2013-05-27T12:11:34.877 回答