8

我正在构建一个 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 秒以 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) 数字,以便我们可以将“不设置动画”表示为 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 回答