8

I have been trying for some time to create a custom segue that does the opposite of the cover vertical (to create a from top to bottom effect animation).I had looked through other questions, google and youtube but cannot get it working.I am completely new to the classes etc. so any help in a step by step guide or video would be so good. I believe that this URL is trying to do something similar to what I want:

http://jrwren.wrenfam.com/blog/2012/02/01/storyboard-custom-segue-for-custom-pushviewcontroller-animation/ , I just cannot get it working.

If any of you know a way to create a segue that is a top to bottom version of the cover vertical segue could you please help me out?

j0k
  • 22,303
  • 28
  • 77
  • 86
BrownEye
  • 969
  • 2
  • 12
  • 20

7 Answers7

8

Well, you would want to create a subclass of UIStoryBoardSegue, like the walkthrough shows you, however under the Storyboard class' .m file(implementation) you would want the following code as your -(void)perform: method -

-(void)perform{
UIViewController *sourceViewController = (UIViewController *) self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) self.destinationViewController;
[sourceViewController.view addSubview:destinationViewController.view];
[destinationViewController.view setFrame:sourceViewController.view.window.frame];
[destinationViewController.view setTransform:CGAffineTransformMakeTranslation(0, -sourceViewController.view.frame.size.height)];
[destinationViewController.view setAlpha:1.0];

[UIView animateWithDuration:0.75
                      delay:0.0
                    options:UIViewAnimationOptionTransitionFlipFromTop
                 animations:^{
                     [destinationViewController.view setTransform:CGAffineTransformMakeTranslation(0, 0)];
                     [destinationViewController.view setAlpha:1.0];
                 }
                 completion:^(BOOL finished){
                     [destinationViewController.view removeFromSuperview];
                     [sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
                 }];}

Hopefully this is helpful.

dmason82
  • 399
  • 7
  • 5
  • After leaving this line `[destinationViewController.view setAlpha:1.0];` out of the animation block, I realise it is needed, but can anyone tell me why? – TimWhiting Oct 14 '15 at 17:28
3

Building on @dmason82's answer, translating to Swift, and simplifying a little, this works for me:

class UIStoryboardSegueFromTop: UIStoryboardSegue {
    override func perform() {
        let src = self.sourceViewController as UIViewController
        let dst = self.destinationViewController as UIViewController

        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        dst.view.transform = CGAffineTransformMakeTranslation(0, -src.view.frame.size.height)

        UIView.animateWithDuration(1.0, animations: {
            dst.view.transform = CGAffineTransformMakeTranslation(0, 0)

            }) { (Finished) in
                src.presentViewController(dst, animated: false, completion: nil)
        }
    }
}
coco
  • 2,634
  • 1
  • 33
  • 53
  • the problem is that the source View Controller is alive as a super view, in a modal transition only the destinationviewconroller should be alive – Eduardo Oliveros Sep 11 '17 at 19:40
2

Here is my implementation of an Opposite Cover Vertical Segue using Storyboards

https://github.com/viccarre/OppositeCoverVerticalSegue

Victor Carreño
  • 232
  • 3
  • 7
1

Hi I just tried the two other answer but it doesn't work as you ask. In order to create a custom segue looking the exact reverse of cover vertical (modal segue default) I created this code :

- (void)perform
{
UIViewController *sourceViewController = self.sourceViewController;
UIViewController *destinationViewController = self.destinationViewController;


[sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
[destinationViewController.view addSubview:sourceViewController.view];
[sourceViewController.view setTransform:CGAffineTransformMakeTranslation(0, 0)];
[sourceViewController.view setAlpha:1.0];

[UIView animateWithDuration:0.75
                      delay:0.0
                    options:UIViewAnimationOptionTransitionFlipFromBottom
                 animations:^{
                     [sourceViewController.view setTransform:CGAffineTransformMakeTranslation(0,destinationViewController.view.frame.size.height)];
                     [sourceViewController.view setAlpha:1.0];
                 }
                 completion:^(BOOL finished){
                     [sourceViewController.view removeFromSuperview];
                     }];

}


@end
1

To complete dmason's answer and have your controller unwind in the opposite direction - going back up from where it came, do this in the presented view controller:

[UIView animateWithDuration:0.75
                      delay:0.0
                    options:UIViewAnimationOptionTransitionFlipFromBottom
                 animations:^{
                     [self.view setTransform:CGAffineTransformMakeTranslation(0, -self.view.frame.size.height)];
                 }
                 completion:^(BOOL finished){
                     [self dismissViewControllerAnimated:NO completion:nil];
                 }
 ];

Bergy's answer didn't work for me.

kanstraktar
  • 5,317
  • 2
  • 20
  • 29
0

dmason's answer is great, and if you want to add an unwind segue so your modal animates properly when it's closed, your perform action could look like this (in a new custom segue class)

- (void)perform
{
    UIViewController *sourceViewController = self.sourceViewController;
    UIViewController *destinationViewController = self.destinationViewController;

    [sourceViewController dismissViewControllerAnimated:NO completion:nil];
    [destinationViewController.view addSubview:sourceViewController.view];

    [UIView animateWithDuration:0.75
                     animations:^{
                         sourceViewController.view.center = CGPointMake(sourceViewController.view.center.x, sourceViewController.view.center.y-600);
                     }
                     completion:^(BOOL finished){
                         [sourceViewController.view removeFromSuperview];
                     }
     ];
}
bergy
  • 1,227
  • 8
  • 11
0

I advise you to use the Hero library to achieve this. It adds a lot of animations and transitions, notably between view controllers : https://github.com/lkzhao/Hero/blob/master/README.md There is an transition called "Cover", and you can choose the direction (left, top, right, bottom)

fredericdnd
  • 908
  • 1
  • 14
  • 24