如何实现一个接一个地结束的动画队列

时间:2014-12-24 10:49:55

标签: ios objective-c core-animation uiviewanimation

所以这就是我想要做的,我希望有一个动画队列发生。这些不能同时发生,因为这会破坏效果,只显示队列中的最后一个动画。如何在开始新动画之前创建一个等待上一个动画完成的队列(在Swift中)?

以下仅显示xpItems数组中的最终动画。<​​/ p>

            var xpItems = XPItem.loadCustomObjectWithKey()
            for (var i = 0; i < xpItems.count; i++) { //for each XP Item.
                let rewardName = xpItems[i].title
                let rewardAmount = xpItems[i].xpAmount
                println(rewardName + " " + String(rewardAmount))

                let currentLevelXPRequired = 100
                let newProgress = CGFloat(rewardAmount) / CGFloat(currentLevelXPRequired) as CGFloat

                self.xpCircle.setProgress(xpCircle.progress + newProgress, animated: true)

            }

//其余代码是Obj-c。

- (void)setProgress:(CGFloat)progress animated:(BOOL)animated
{
    if (self.progress == progress) {
        return;
    }
    if (animated == NO) {
        if (_displayLink) {
            //Kill running animations
            [_displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
            _displayLink = nil;
        }
        [self setNeedsDisplay];
    } else {
        _animationStartTime = CACurrentMediaTime();
        _animationFromValue = self.progress;
        _animationToValue = progress;
        if (!_displayLink) {
            //Create and setup the display link
            [self.displayLink removeFromRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
            self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animateProgress:)];
            [self.displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
        } /*else {
            //Reuse the current display link
        }*/
    }
}


- (void)animateProgress:(CADisplayLink *)displayLink
{
    dispatch_async(dispatch_get_main_queue(), ^{
        CGFloat dt = (displayLink.timestamp - _animationStartTime) / self.animationDuration;
        if (dt >= 1.0) {
            //Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
            [self.displayLink removeFromRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
            self.displayLink = nil;
            [super setProgress:_animationToValue animated:NO];
            [self setNeedsDisplay];
            return;
        }

        //Set progress
        [super setProgress:_animationFromValue + dt * (_animationToValue - _animationFromValue) animated:YES];
        [self setNeedsDisplay];

    });
}

super.setProgress [..]:

- (void)setProgress:(CGFloat)progress animated:(BOOL)animated
{
    _progress = progress;
}

很抱歉让代码在obj-c / swift中。

1 个答案:

答案 0 :(得分:4)

大多数动画方法,当然在UIKit中都有一个完成处理程序,可以在动画完成时自动调用。您需要做的就是创建一个UIView s或其他对象的数组,然后您可以在其上执行动画(可能是CGPoint的数组),然后按顺序为所有对象设置动画。 E.g:

- (void)animateArrayWithCompletion:(void(^)(void))handler
{
    if (!viewArray.count) {
        if (handler) {
            handler();
        }
    }
    else {
        UIView *myView = viewArray.lastObject;
        [viewArray removeObject:myView];
        CGRect frame = myView.frame;
        frame.origin.x += 100;
        [UIView animateWithDuration:1 animations:^{
            myView.frame = frame;
        } completion:^(BOOL complete) {
            [self animateArrayWithCompletion:handler];
        }];   
    }
}