Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I begin to replicate the custom view controller transition Apple uses as the default in iOS 7?

Using iOS 7's custom view controller transitions, I want to achieve a visual effect similar to Apple's default view controller transition in iOS 7.

(The one where you can slide to pop a view controller off the stack by sliding it from the left to the right, where the top view controller slides off the top of the other with a shadow and the navigation bar shifts.)

enter image description here

I'm having a great deal of difficulty implementing this, though. Most of the tutorials on custom view controllers go with very different effects than the default in order to show what the API is capable off, but I want to replicate this one.

In my subclass for implementing <UIViewControllerAnimatedTransitioning> I have the following code for the interactive animation:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    [transitionContext.containerView addSubview:toViewController.view];
    [transitionContext.containerView addSubview:fromViewController.view];

    fromViewController.view.layer.shadowOffset = CGSizeMake(0.0, 0.0);
    fromViewController.view.layer.shadowColor = [UIColor blackColor].CGColor;
    fromViewController.view.layer.shadowRadius = 5.0;
    fromViewController.view.layer.shadowOpacity = 0.5;

    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
        CGRect newFrame = fromViewController.view.frame;
        newFrame.origin.x = CGRectGetWidth(fromViewController.view.bounds);

        fromViewController.view.frame = newFrame;
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:!transitionContext.transitionWasCancelled];
    }];
}

However the shadow code makes it lag tremendously (even if I use the new snapshot methods) and I cannot figure out how to manipulate the navigation bar at all.

Has anyone tried to do something similar to this and are able to provide sample code?

Sample project for testing if you'd like: https://dzwonsemrish7.cloudfront.net/items/43260h1u1T1u010i0V3C/DefaultVCTransition.zip

Credit to objc.io for the base code.

like image 291
Doug Smith Avatar asked Mar 25 '14 03:03

Doug Smith


1 Answers

Setting the shadowPath greatly increases the performance of this shadow.

Just add this in your animateTransition: method after you have set the shadow properties. This avoids the expensive offscreen rendering that shadow normally causes.

[fromViewController.view.layer setShadowPath:[[UIBezierPath bezierPathWithRect:fromViewController.view.bounds] CGPath]];

I downloaded your sample project and did that, the stutter is now completely gone.

Some info on what this does here.

EDIT:

The answer about manipulating the navigation bar animation is that it doesn't seem like you can. In order to do so you will need to reimplement your own NavigationController-type class from scratch. The transition animation for the navigation bar is done internally by the container view controller (the UINavigationController) and is not surfaced anywhere in the code.

like image 91
Dima Avatar answered Oct 17 '22 02:10

Dima