dismissModalViewController with transition: left to right

后端 未结 3 1228
夕颜
夕颜 2020-12-08 05:17

I was using a nice method to dismiss my modal view controller:

[self dismissModalViewControllerWithTransition:2];

which makes a slide trans

相关标签:
3条回答
  • 2020-12-08 05:50

    I have accepted the answer from Safecase, but I would like to publish my final solution here:

    1) To present a modal view controller with a from right to left transition I have written following method:

    -(void) presentModalView:(UIViewController *)controller {
        CATransition *transition = [CATransition animation];
        transition.duration = 0.35;
        transition.timingFunction =
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type = kCATransitionMoveIn;
        transition.subtype = kCATransitionFromRight;
    
        // NSLog(@"%s: self.view.window=%@", _func_, self.view.window);
        UIView *containerView = self.view.window;
        [containerView.layer addAnimation:transition forKey:nil];
        [self presentModalViewController:controller animated:NO];
    }
    

    2) To dismiss a modal view with an slide transition left to right:

    -(void) dismissMe {
        CATransition *transition = [CATransition animation];
        transition.duration = 0.35;
        transition.timingFunction =
        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type = kCATransitionMoveIn;
        transition.subtype = kCATransitionFromLeft;
    
        // NSLog(@"%s: controller.view.window=%@", _func_, controller.view.window);
        UIView *containerView = self.view.window;
        [containerView.layer addAnimation:transition forKey:nil];
    
        [self dismissModalViewControllerAnimated:NO];
    }
    

    Thanks guys!

    0 讨论(0)
  • 2020-12-08 06:02

    This Swift 4 ModalService class below is a pre-packaged flexible solution that can be dropped into a project and called from anywhere it is required. This class brings the modal view in on top of the current view from the specified direction, and then moves it out to reveal the original view behind it when it exits. Given a presentingViewController that is currently being displayed and a modalViewController that you have created and wish to display, you simply call:

    ModalService.present(modalViewController, presenter: presentingViewController)
    

    Then, to dismiss, call:

    ModalService.dismiss(modalViewController)
    

    This can of course be called from the modalViewController itself as ModalService.dismiss(self). Note that dismissing does not have to be called from the presentingViewController, and does not require knowledge of or a reference to the original presentingViewController.

    The class provides sensible defaults, including transitioning the modal view in from the right and out to the left. This transition direction can be customised by passing a direction, which can be customised for both entry and exit:

    ModalService.present(modalViewController, presenter: presentingViewController, enterFrom: .left)
    

    and

    ModalService.dismiss(self, exitTo: .left)
    

    This can be set as .left, .right, .top and .bottom. You can likewise pass a custom duration in seconds if you wish:

    ModalService.present(modalViewController, presenter: presentingViewController, enterFrom: .left, duration: 0.5)
    

    and

    ModalService.dismiss(self, exitTo: .left, duration: 2.0)
    

    Head nod to @jcdmb for the Objective C answer on this question which formed the kernel of the solution in this class.


    Here's the full class. The values returned by the private transitionSubtype look odd but are set this way deliberately. You should test the observed behaviour before assuming these need 'correcting'. :)

    import UIKit
    
    class ModalService {
    
        enum presentationDirection {
            case left
            case right
            case top
            case bottom
        }
    
        class func present(_ modalViewController: UIViewController,
                           presenter fromViewController: UIViewController,
                           enterFrom direction: presentationDirection = .right,
                           duration: CFTimeInterval = 0.3) {
            let transition = CATransition()
            transition.duration = duration
            transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            transition.type = kCATransitionMoveIn
            transition.subtype = ModalService.transitionSubtype(for: direction)
            let containerView: UIView? = fromViewController.view.window
            containerView?.layer.add(transition, forKey: nil)
            fromViewController.present(modalViewController, animated: false)
        }
    
        class func dismiss(_ modalViewController: UIViewController,
                           exitTo direction: presentationDirection = .right,
                           duration: CFTimeInterval = 0.3) {
            let transition = CATransition()
            transition.duration = duration
            transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            transition.type = kCATransitionReveal
            transition.subtype = ModalService.transitionSubtype(for: direction, forExit: true)
            if let layer = modalViewController.view?.window?.layer {
                layer.add(transition, forKey: nil)
            }
            modalViewController.dismiss(animated: false)
        }
    
        private class func transitionSubtype(for direction: presentationDirection, forExit: Bool = false) -> String {
            if (forExit == false) {
                switch direction {
                case .left:
                    return kCATransitionFromLeft
                case .right:
                    return kCATransitionFromRight
                case .top:
                    return kCATransitionFromBottom
                case .bottom:
                    return kCATransitionFromTop
                }
            } else {
                switch direction {
                case .left:
                    return kCATransitionFromRight
                case .right:
                    return kCATransitionFromLeft
                case .top:
                    return kCATransitionFromTop
                case .bottom:
                    return kCATransitionFromBottom
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-08 06:10

    Try this:

    I asume you are dismissing a view controller 2 from view controller 1. In view controller 2 you are using this

    [self  dismissModalViewControlleAnimated: NO]];
    

    Now In the first view controller, in viewWillAppear: method add the code

    CATransition *animation = [CATransition animation];
    
    [animation setDelegate:self];
    [animation setType:kCATransitionPush];
    [animation setSubtype:kCATransitionFromLeft];
    
    [animation setDuration:0.50];
    [animation setTimingFunction:
     [CAMediaTimingFunction functionWithName:
      kCAMediaTimingFunctionEaseInEaseOut]];
    
    
    [self.view.layer addAnimation:animation forKey:kCATransition];
    
    0 讨论(0)
提交回复
热议问题