使用UIView动画处理动画链的最佳方法

时间:2013-03-22 16:17:51

标签: iphone ios objective-c uiviewanimation uicolor

我正在构建一个iOS应用程序,在这个应用程序中,我需要通过选择颜色来实现动画视图的backgroundColor。在我的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];
                     }
     ];
}

完成处理程序触发包含下一个颜色的第二个方法....

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

等等......这一直持续到第七个动画中我在完成时调用[self beginFirstStageBackgroundAnimation];以再次开始该过程。

当我使用后退按钮离开视图时,在viewDidDisappear中或当显示器上的计时器结束时,我运行[self.view.layer removeAllAnimations];以完全摆脱动画。然而,该应用程序运行并完全按预期工作,但似乎在离开视图并运行整体后崩溃,虽然我不知道为什么它似乎与此动画链相关。

是否有更好的解决方案,每隔3秒钟为视图的backgroundColor设置动画,延迟时间为3秒?

[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
}

3 个答案:

答案 0 :(得分:7)

我认为要走的路是在参数化上代表你想要在每个动画中发生的事情(在这种情况下只是一种颜色),然后将这些参数保存在一个数组中。该数组就像您的动画待办事项列表:

@property(strong, nonatomic) NSArray *animationTodo;

我们还需要跟踪列表中的位置。使用盒装(NS)编号,以便我们可以将“不动画”表示为零,与索引零不同:

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

答案 1 :(得分: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"];
}

答案 2 :(得分:-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];
                     }
     ];
 }
}

您可以将代码发布到“使用后退按钮离开视图”吗?问题可能就在那里......