Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Segue Animation

I am trying to use a custom segue to perform a kind of zoom animation. When the transition is executed, the sourceViewController goes black, then the zoom occurs.

Tried also to set the pushViewController: into the completion block but the transition is not executed at all.

- (void)perform {

    UIViewController *sourceViewController = (UIViewController *) self.sourceViewController;
    UIViewController *destinationViewController = (UIViewController *) self.destinationViewController;

    [destinationViewController.view setTransform:CGAffineTransformMakeScale(0.5,0.5)];
    [destinationViewController.view setAlpha:0.0];

    [UIView animateWithDuration:0.5
                          delay:0.0
                        options:UIViewAnimationCurveEaseOut 
                     animations:^{
                         [destinationViewController.view setTransform:CGAffineTransformMakeScale(1.0,1.0)];
                         [destinationViewController.view setAlpha:1.0];
                         [sourceViewController.navigationController pushViewController:destinationViewController animated:NO];
                     } 
                     completion:^(BOOL finished){
                     }];

}

What I am doing wrong ?

like image 376
Nimrod7 Avatar asked May 28 '12 05:05

Nimrod7


People also ask

How do you create a segue?

The segue needs to connect from the view controller itself so nothing else triggers it. To create a segue from the controller Control-drag from the View Controller icon to the Exit icon. Give this new segue the identifier unwind to reference it from the code.

What happens in the segue transition?

A segue is a smooth transition. When you segue in conversation, you change the topic so smoothly that people might not even notice.


1 Answers

It feels kludgy, but you can try adding the destinationViewController.view as a subview before your animation and then when the animation is done, remove it and push it back on without animation. Solves the black screen before the transition, but perhaps not perfect, depending upon what you want to do with the navigation bar, but maybe closer:

[sourceViewController.view addSubview:destinationViewController.view];
[destinationViewController.view setFrame:sourceViewController.view.window.frame];
[destinationViewController.view setTransform:CGAffineTransformMakeScale(0.5,0.5)];
[destinationViewController.view setAlpha:1.0];

[UIView animateWithDuration:0.5
                      delay:0.0
                    options:UIViewAnimationCurveEaseOut 
                 animations:^{
                     [destinationViewController.view setTransform:CGAffineTransformMakeScale(1.0,1.0)];
                     [destinationViewController.view setAlpha:1.0];
                 } 
                 completion:^(BOOL finished){
                     [destinationViewController.view removeFromSuperview];
                     [sourceViewController.navigationController pushViewController:destinationViewController animated:NO];
                 }];

Note, effective iOS 7, you would use custom transitions. For more information, see WWDC 2013 Custom Transitions Using View Controllers.

For example, if trying to do a custom transition with navigation controller, the first view controller would specify itself as the delegate of the navigation controller:

self.navigationController.delegate = self;

Then, it would specify the custom animators for push and pop, respectively:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController *)fromVC
                                                 toViewController:(UIViewController *)toVC
{
    if (operation == UINavigationControllerOperationPush) {
        return [[PushAnimator alloc] init];
    } else {
        return [[PopAnimator alloc] init];
    }
}

And then you'd obviously implement these animators:

@interface PushAnimator : NSObject <UIViewControllerAnimatedTransitioning>

@end

@implementation PushAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.5;
}

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

    [[transitionContext containerView] addSubview:toViewController.view];
    toViewController.view.frame = fromViewController.view.frame;
    toViewController.view.transform = CGAffineTransformMakeScale(0.5,0.5);
    toViewController.view.alpha = 0.0;

    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 options:0 animations:^{
        toViewController.view.transform = CGAffineTransformIdentity;
        toViewController.view.alpha = 1.0;
    } completion:^(BOOL finished) {
        [fromViewController.view removeFromSuperview];
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end

and

@interface PopAnimator : NSObject <UIViewControllerAnimatedTransitioning>

@end

@implementation PopAnimator

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.5;
}

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

    [[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view];
    toViewController.view.frame = fromViewController.view.frame;

    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 options:0 animations:^{
        fromViewController.view.transform = CGAffineTransformMakeScale(0.5,0.5);
        fromViewController.view.alpha = 0.0;
    } completion:^(BOOL finished) {
        [fromViewController.view removeFromSuperview];
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

@end
like image 98
Rob Avatar answered Nov 09 '22 22:11

Rob