9

3 つの UIView をアニメーション化する必要があります (フェードイン/フェードアウト)。1 アニメーションの長さは 0.6 秒です (フェードイン/アウトのサイクルは 0.6+0.6 秒です)。しかし、アニメーションを 0.2 秒で起動する必要があります。

  • 最初のアニメーションは 0.0 秒で起動する必要があります。
  • 2 番目のアニメーションは 0.2 秒で起動する必要があります。
  • 3 番目のアニメーションは 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 はアルファ、X は時間です。上位 3 つのグラフ - 必要なもの。下のもの - 私が現在持っているもの。強調表示された領域は、問題が発生する場所です。2 番目のビューのアニメーションが 0.2 秒間フリーズし、3 番目のビューと同期していることがわかります。そのため、同じフェーズで点滅を開始します。これはほんの一例です。アニメーション化できる場合もあれば、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

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 に答える
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 に答える
-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 に答える