I have a content UIViewController that presents a settings UIViewController using a custom transition. The presentation is with presentViewController
A few potential gotchas with dismissal of modally presented view controllers using custom transition animations:
Given all that, I think this should work:
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView = transitionContext.containerView;
const BOOL isUnwinding = [toController presentedViewController] == fromController;
const BOOL isPresenting = !isUnwinding;
UIViewController *presentingController = isPresenting ? fromController : toController;
UIViewController *presentedController = isPresenting ? toController : fromController;
[containerView addSubview:presentingController.view];
[containerView bringSubviewToFront:presentingController.view];
if(isPresenting)
{
// Set up the initial position of the presented settings controller. Scale it down so it seems in the distance. Alpha it down so it is dark and shadowed.
presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
presentedController.view.alpha = 0.7;
[UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
// Lift up the presented controller.
presentedController.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
// Brighten the presented controller (out of shadow).
presentedController.view.alpha = 1;
// Push the presenting controller down the screen – 3d effect to be added later.
presentingController.view.layer.transform = CATransform3DMakeTranslation(0,400,0);
} completion: ^(BOOL finished){
[transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
}];
}
else
{
presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
presentedController.view.alpha = 0.7;
[UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
// Bring the presenting controller back to its original position.
presentingController.view.layer.transform = CATransform3DIdentity;
// Lower the presented controller again and put it back in to shade.
presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
presentedController.view.alpha = 0.4;
} completion:^(BOOL finished) {
[transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
}];
}
}
Initially, I thought about using CATransition
to have custom transition effect when presentViewController:animated:completion:
and dismissViewControllerAnimated:completion:
a View Controller. But you want to show a portion of View Controller when the setting View Controller is presented, then I think CATransition
would not help because you don't have full control of how far you want to move the View Controller.
I think the easiest way is to have one single View Controller with two full screen UIView. For the first UIView (View Controller's view, that is, self.view), you layout the setting, and on the second UIView, it's the regular View. In the ViewDidLoad, you add the 2nd view by using [self.view addSubview:2ndView];
. Later when you want to present the setting view, you can do
CGRect frame = secondView.frame;
frame.origin.y = the_y_coordinate_you_like;
UIView animateWithDuration:0.2 animations:^{
secondView.frame = frame;
}];
then do the other way to bring the 2ndView back.