8

私は、色の選択を通じてアニメーションへのビューのbackgroundColorの要件があるiOSアプリケーションを構築しています。私のviewDidLoadメソッドでは、基本的に次を使用してUIViewアニメーションのチェーンを起動しています。

-(void) beginFirstStageBackgroundAnimation
{
    [UIView animateWithDuration: 3.0f
                          delay: 3.0f
                        options: UIViewAnimationOptionTransitionCrossDissolve
                     animations:^{
                         self.view.backgroundColor = [UIColor colorWithRed: 251./255 green:203./255 blue:147./255 alpha:1.0];
                     }
                     completion:^(BOOL finished){
                         [self secondStageBackgroundAnimation];
                     }
     ];
}

完了ハンドラーは、次の色を含む2番目のメソッドを起動します。

-(void) secondStageBackgroundAnimation
{
    [UIView animateWithDuration: 3.0f
                          delay: 3.0f
                        options: UIViewAnimationOptionTransitionCrossDissolve
                     animations:^{
                         self.view.backgroundColor = [UIColor colorWithRed:251./255 green:224./255 blue:96./255 alpha:1.0];
                     }
                     completion:^(BOOL finished){
                         [self thirdStageBackgroundAnimation];
                     }
     ];
}

など...これは、7番目のアニメーションで[self beginFirstStageBackgroundAnimation];、プロセスを再開するために完了を呼び出すまで続きます。

戻るボタンでビューを離れるとき、viewDidDisappearで、またはディスプレイのタイマーが終了するとき[self.view.layer removeAllAnimations];、アニメーションを完全に取り除くために実行します。ただし、アプリは意図したとおりに実行および動作しますが、ビューを離れて全体を実行するとクラッシュするようです。理由はわかりませんが、このアニメーションチェーンに関連しているようです。

3秒の遅延で3秒ごとにビューのbackgroundColorをアニメーション化するためのより良い解決策はありますか?

そして、[self.view.layer removeAllAnimations];実際に私がやりたいことをしますか?

編集:私がビューを離れるコードは次のとおりです:

-(void) backBtnPressed:(id)sender
{
    [self stopAudio]; // stop audio that is playing.
    [self.view.layer removeAllAnimations]; // remove all animations?
    [self.navigationController popViewControllerAnimated: YES]; // pop view from stack
}
4

3 に答える 3

7

進むべき道は、各アニメーションで何をしたいのかをパラメトリックに表現し(この場合は単なる色です)、それらのパラメーターを配列に保持することだと思います。配列は、アニメーションのやることリストのようなものです。

@property(strong, nonatomic) NSArray *animationTodo;

また、リストのどこにいるかを追跡する必要があります。ボックス化された(NS)数値を使用して、「アニメーション化しない」をインデックス0とは異なるnilとして表すことができるようにします。

@property(strong, nonatomic) NSNumber *animationIndex;

配列は色で初期化されます:

self.animationTodo = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], ... nil];

これで、アニメーションを単一のメソッドに圧縮できます。

- (void)animate {

    if (!animationIndex) return;
    NSInteger index = [animationIndex intValue];
    [UIView animateWithDuration:3.0 animations:^{
        self.view.backgroundColor = [animationToDo objectAtIndex:index];
    } completion:^(BOOL finished) {
        NSInteger nextIndex = (index==self.animationTodo.count-1)? 0 : index+1;  // advance index in a ring
        self.animationIndex = [NSNumber numberWithInt:nextIndex];
        // schedule the next one in 3s
        [self performSelector:@selector(animate) withObject:nil afterDelay:3.0];
    }];
}

セレクターを実行すると、遅延を指定できます。また、次のアニメーションを開始するたびにスタックを巻き上げないというプラスの効果もあります。

停止も簡単になりました。ビューが消える前、および停止したいときはいつでもこれを行ってください。

- (void)stopAnimating {

    self.animationIndex = nil;
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
}
于 2013-03-22T17:14:27.663 に答える
5

使ってみるとCAAnimation色やアニメーションの管理がしやすくなると思います

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    NSArray *colors = @[[UIColor greenColor],
                        [UIColor redColor],
                        [UIColor blueColor],
                        [UIColor yellowColor],
                        [UIColor orangeColor]
                        ];
    NSMutableArray *animations = [NSMutableArray new];
    float colorAnimationDuration = 3.0f;
    for (int i = 0; i < colors.count; i++)
    {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
        animation.toValue = (id)[[colors objectAtIndex:i] CGColor];
        animation.duration = colorAnimationDuration;
        animation.beginTime = i * colorAnimationDuration;
        animation.removedOnCompletion = NO;
        animation.fillMode = kCAFillModeForwards;

        [animations addObject:animation];
    }

    CAAnimationGroup *animationsGroup = [CAAnimationGroup new];
    animationsGroup.duration = colors.count * colorAnimationDuration;
    animationsGroup.repeatCount = HUGE_VALF;
    animationsGroup.animations = animations;

    [self.view.layer addAnimation:animationsGroup forKey:@"myAnimations"];

}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.view.layer removeAnimationForKey:@"myAnimations"];
}
于 2013-03-22T16:42:27.140 に答える
-1

次のように、すべてのアニメーションメソッド内にチェックを追加してみてください。

-(void) secondStageBackgroundAnimation
 {
 if (self.view.superview){
    [UIView animateWithDuration: 3.0f
                          delay: 3.0f
                        options: UIViewAnimationOptionTransitionCrossDissolve
                     animations:^{
                         self.view.backgroundColor = [UIColor colorWithRed:251./255 green:224./255 blue:96./255 alpha:1.0];
                     }
                     completion:^(BOOL finished){
                         [self thirdStageBackgroundAnimation];
                     }
     ];
 }
}

「戻るボタンでビューを離れる」コードを投稿できますか?問題はそこにある可能性があります...

于 2013-03-22T16:37:41.520 に答える