为什么animateWithDuration动画和完成块之间的暂停?(Why the pause b

2019-09-17 01:34发布

继苹果公司的建议,我通过把后续调用链的UIView动画-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];
    }];
}];

该动画的所有执行正确的顺序,但它们之间有一个微小的延迟,尤其是前-transitionWithView:duration:options:animations:completion:调用。 如何理顺动画步骤之间的转换?

Answer 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];

需要注意的是牛肉是前六行中,所有剩下的只是为了保持完整性。



Answer 2:

因为你没有延迟形容我链式动画。

您正在使用transitionWithView:持续时间:选择:动画:完成:与动画块是给pushViewController呼叫:动画:. 这没有任何意义,我。

transitionWithView:持续时间:选择:动画:完成转变从一个子视图下。

pushViewController:动画是推动导航控制器堆栈上的视图控制器导航控制器方法。 使用这些2在一起是没有意义的我。

如果你希望你的规模的动画与推结束,那么就直接从你的完成块调用推送动画。



Answer 3:

在我的经验中,“使用完毕块链动画”简直是有缺陷的(让子动画之间的小停顿)。 我确信没有的loadView / viewDidLoad中/ viewWillAppear中/ viewWillLayoutSubviews滥用回事。

完全相同的代码口吃与“竣工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
            ...
        })


文章来源: Why the pause between animateWithDuration animation and completion blocks?