Following Apple's recommendations, I'm chaining UIView animations by putting subsequent calls to -animationWithDuration:animation:
in the completion:
block of another call to aanimateWithDuration:animation:completion:
, like so:
[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];
}];
}];
The animations all execute the right order, but there is a tiny delay between them, especially before the -transitionWithView:duration:options:animations:completion:
call. How do I smooth out the transitions between animation steps?
Aside:
Is there any particular reason why you are abusing a navigation controller in this way? Couldn’t you just use presentViewController:animated:completion:
setting its transition style to UIModalTransitionStyleFlipHorizontal
?
Back to your question:
I’m pretty much sure that the stutter comes from the simple fact that pushViewController:animated:
implicitly has to load the view of the view controller that is to be pushed and that this takes some time.
So if you cannot use the presentViewController:animated:completion:
(or presentModalViewController:animated: if you have to support iOS 4) approach, I’d encourage you to try this:
// 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];
Note that the beef is within the first six lines, all the rest is just for completeness.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With