为什么animateWithDuration动画和完成块之间的暂停?

时间:2012-05-06 05:21:16

标签: cocoa-touch uiview uinavigationcontroller core-animation uiviewanimationtransition

按照Apple的建议,我通过在-animationWithDuration:animation:的另一个completion:aanimateWithDuration:animation:completion:块中随后调用[UIView animateWithDuration:scaleDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ // Scale the controllers' views down. self.view.transform = CGAffineTransformScale(self.view.transform, 0.8, 0.8); } completion:^(BOOL finished) { // Transition to the new view and push on the new view controller. [UIView transitionWithView:self.view duration:1 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft animations:^{ [self pushViewController:viewController animated:NO]; } completion:^(BOOL finished) { [UIView animateWithDuration:scaleDuration delay:0 options:UIViewAnimationOptionCurveLinear animations: ^{ // Scale back to the original size. self.view.transform = CGAffineTransformScale(self.view.transform, 1.25, 1.25); } completion:nil]; }]; }]; 来链接UIView动画,如下所示:

-transitionWithView:duration:options:animations:completion:

动画都执行正确的顺序,但它们之间存在微小的延迟,尤其是在{{1}}调用之前。如何平滑动画步骤之间的过渡?

3 个答案:

答案 0 :(得分:1)

除了:
为什么以这种方式滥用导航控制器有什么特别的原因吗?您是否只能使用presentViewController:animated:completion:将其过渡方式设置为UIModalTransitionStyleFlipHorizontal

回到你的问题:

我非常确定口吃来自于pushViewController:animated:隐含地必须加载要推送的视图控制器的视图并且这需要一些时间的简单事实。

因此,如果您无法使用presentViewController:animated:completion:(或presentModalViewController:动画:如果您必须支持iOS 4)方法,我建议您尝试这样做:

// ensure the view is already loaded when you invoke `pushViewController:animated:`
[viewController view];

// there is no strict need to calculate those in situ, so we do it up front
CGAffineTransform originalTransform = self.view.transform;
CGAffineTransform downscalingTransform = CGAffineTransformScale(originalTransform, 0.8, 0.8);

// I found it hard to read the block-in-a-block-in-a... while editing here, so I've taken them apart:
void (^scaleDownAnimation)() = ^{
    self.view.transform = downscalingTransform;
};

void (^restoreScaleAnimation)() = ^{
    self.view.transform = originalTransform;
};

void (^pushControllerAnimation)() = ^{
    [self pushViewController:viewController animated:NO];
};

void (^pushAnimationCompletion)(BOOL) = ^(BOOL unused) {
    [UIView animateWithDuration:scaleDuration
                          delay:0
                        options:UIViewAnimationOptionCurveLinear
                     animations:restoreScaleAnimation
                     completion:nil];
};

void (^downscaleCompletion)(BOOL) = ^(BOOL unused){
    UIViewAnimationOptions linearFlipFromLeft = UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft;
    [UIView transitionWithView:self.view
                      duration:1
                       options:linearFlipFromLeft
                    animations:pushControllerAnimation
                    completion:pushAnimationCompletion];
};

[UIView animateWithDuration:scaleDuration
                      delay:0
                    options:UIViewAnimationOptionCurveEaseIn
                 animations:scaleDown
                 completion:downscaleCompletion];

注意牛肉在前六行内,剩下的只是为了完整。

答案 1 :(得分:0)

我已经链接了动画,因为你没有延迟地描述。

您正在使用transitionWithView:duration:options:animations:completion:动画块是对pushViewController的调用:animated:。这对我没有任何意义。

transitionWithView:duration:options:animations:完成从一个子视图转换到下一个子视图。

pushViewController:animated是一种导航控制器方法,用于推送导航控制器堆栈上的视图控制器。一起使用这两个对我来说毫无意义。

如果您希望缩放动画以推送结束,则只需直接从完成块调用推送动画。

答案 2 :(得分:0)

根据我的经验,"使用完成块链接动画"只是有缺陷(在子动画之间暂停)。我确定没有loadView / viewDidLoad / viewWillAppear / viewWillLayoutSubviews滥用行为。

完全相同的代码与" completion-block_chainig"断断续续。但如果我重新使用关键帧,那就可以了。

所以,而不是(例如)......

        UIView.animate(withDuration: 1, animations: {[weak self] in
            ...
            self?.view.layoutIfNeeded()
        }, completion: { [weak self] _ in
            UIView.animate(withDuration: 1, animations: {
                ...
                self?.view.layoutIfNeeded()
            }, completion: { [weak self] _ in
                UIView.animate(withDuration: 1, animations: {
                    ...
                    self?.view.layoutIfNeeded()
                }, completion: { [weak self] _ in
                    ...
                })
            })
        })

......我更喜欢......

        UIView.animateKeyframes(withDuration: 3, delay: 0, options: .calculationModeLinear, animations: {[weak self] in

            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.33, animations: {[weak self] in
                ...
                self?.view.layoutIfNeeded()
            })

            UIView.addKeyframe(withRelativeStartTime: 0.33, relativeDuration: 0.33, animations: {[weak self] in
                ...
                self?.view.layoutIfNeeded()
            })

            UIView.addKeyframe(withRelativeStartTime: 0.66, relativeDuration: 0.33, animations: {[weak self] in
                ...
                self?.view.layoutIfNeeded()
            })

        }, completion: { [weak self] _ in
            ...
        })