Skip to content

Instantly share code, notes, and snippets.

@IamMarik
Last active March 25, 2020 10:32

Revisions

  1. IamMarik revised this gist Mar 25, 2020. 1 changed file with 56 additions and 108 deletions.
    164 changes: 56 additions & 108 deletions Customtransition.swift
    Original file line number Diff line number Diff line change
    @@ -1,18 +1,60 @@
    //
    // MenuViewController.swift
    // Mullt
    //
    // Created by Marik on 09.03.2020.
    // Copyright © 2020 Marik. All rights reserved.
    //

    import UIKit

    class MenuViewController: UIViewController {

    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    modalPresentationStyle = .custom
    }

    override func viewDidLoad() {
    super.viewDidLoad()
    }



    @IBAction func toModule1(_ sender: Any) {
    if let menuController = self.navigationController as? MenuNavigationController {
    let controller = UIStoryboard(name: "Module1", bundle: nil).instantiateInitialViewController()! as! UINavigationController
    menuController.presentNavigationController(controller, animated: false)
    }
    }


    @IBAction func toModule1Sub(_ sender: Any) {
    if let menuController = self.navigationController as? MenuNavigationController {
    let controller = UIStoryboard(name: "Module1", bundle: nil).instantiateInitialViewController()! as! UINavigationController
    menuController.presentNavigationController(controller, animated: true)
    }
    }

    }

    class MenuNavigationController: UINavigationController {
    var customTransitionDelegate = TransitionDelegate()

    weak var presentedController: UINavigationController?
    var interactionController: UIPercentDrivenInteractiveTransition?
    var interactiveTransition: UIPercentDrivenInteractiveTransition?


    func presentNavigationController(_ controller: UINavigationController, animated: Bool) {
    controller.modalPresentationStyle = .custom
    controller.transitioningDelegate = self.customTransitionDelegate
    let panDown = UIPanGestureRecognizer(target: self, action: #selector(handleDissmiss(_:)))
    controller.view.addGestureRecognizer(panDown)
    self.present(controller, animated: animated) {
    self.presentedController = controller
    func presentNavigationController(_ navController: UINavigationController, animated: Bool) {
    navController.modalPresentationStyle = .custom
    navController.transitioningDelegate = self.customTransitionDelegate
    if let firstController = navController.viewControllers.first {
    let panDown = UIPanGestureRecognizer(target: self, action: #selector(handleDissmiss(_:)))
    firstController.view.addGestureRecognizer(panDown)
    }
    self.present(navController, animated: animated) {
    self.presentedController = navController
    }
    }

    @@ -21,118 +63,24 @@ class MenuNavigationController: UINavigationController {
    let percent = translate.x / gesture.view!.bounds.size.width
    if gesture.state == .began {
    if gesture.location(in: gesture.view).x / gesture.view!.bounds.size.width < 0.3 {
    interactionController = UIPercentDrivenInteractiveTransition()
    customTransitionDelegate.interactionController = interactionController
    interactiveTransition = UIPercentDrivenInteractiveTransition()
    customTransitionDelegate.interactionController = interactiveTransition
    self.dismiss(animated: true, completion: nil)
    }
    } else if gesture.state == .changed {
    interactionController?.update(percent)
    interactiveTransition?.update(percent)
    } else if gesture.state == .ended || gesture.state == .cancelled {
    let velocity = gesture.velocity(in: gesture.view)
    print(velocity)
    print(percent)
    if percent > 0.5 || velocity.x > 500 {
    interactionController?.finish()
    interactiveTransition?.finish()
    } else {
    interactionController?.cancel()
    interactiveTransition?.cancel()
    }
    interactionController = nil
    interactiveTransition = nil
    }
    }

    }



    class TransitionDelegate: NSObject, UIViewControllerTransitioningDelegate {

    weak var interactionController: UIPercentDrivenInteractiveTransition?

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return PullRightAnimationController(transitionType: .presenting)
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return PullRightAnimationController(transitionType: .dismissing)
    }

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    return PresentationController(presentedViewController: presented, presenting: presenting)
    }

    func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    return interactionController
    }

    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    return interactionController
    }

    }

    class PullRightAnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    enum TransitionType {
    case presenting
    case dismissing
    }

    let transitionType: TransitionType

    init(transitionType: TransitionType) {
    self.transitionType = transitionType
    super.init()
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.3
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    let inView = transitionContext.containerView
    let toView = transitionContext.view(forKey: .to)!
    let fromView = transitionContext.view(forKey: .from)!

    var frame = inView.bounds

    switch transitionType {
    case .presenting:

    toView.frame = frame.offsetBy(dx: frame.size.width, dy: 0)
    inView.insertSubview(toView, aboveSubview: fromView)

    UIView.animate(withDuration: transitionDuration(using: transitionContext),
    delay: 0,
    options: .curveLinear,
    animations: {

    //frame.origin.x = -frame.width
    toView.frame = frame

    }, completion: { finished in
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
    })
    case .dismissing:

    frame.origin.x = -frame.size.width
    toView.frame = frame

    inView.addSubview(toView)

    UIView.animate(withDuration: transitionDuration(using: transitionContext),
    delay: 0,
    options: .curveLinear,
    animations: {
    toView.frame = inView.bounds
    fromView.frame = CGRect(x: frame.width, y: 0, width: frame.width, height: frame.height)
    }, completion: { finished in
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
    })
    }
    }

    }

    class PresentationController: UIPresentationController {
    override var shouldRemovePresentersView: Bool { return true }
    }
  2. IamMarik revised this gist Mar 9, 2020. 1 changed file with 95 additions and 0 deletions.
    95 changes: 95 additions & 0 deletions Customtransition.swift
    Original file line number Diff line number Diff line change
    @@ -41,3 +41,98 @@ class MenuNavigationController: UINavigationController {
    }

    }



    class TransitionDelegate: NSObject, UIViewControllerTransitioningDelegate {

    weak var interactionController: UIPercentDrivenInteractiveTransition?

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return PullRightAnimationController(transitionType: .presenting)
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return PullRightAnimationController(transitionType: .dismissing)
    }

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    return PresentationController(presentedViewController: presented, presenting: presenting)
    }

    func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    return interactionController
    }

    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
    return interactionController
    }

    }

    class PullRightAnimationController: NSObject, UIViewControllerAnimatedTransitioning {

    enum TransitionType {
    case presenting
    case dismissing
    }

    let transitionType: TransitionType

    init(transitionType: TransitionType) {
    self.transitionType = transitionType
    super.init()
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.3
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    let inView = transitionContext.containerView
    let toView = transitionContext.view(forKey: .to)!
    let fromView = transitionContext.view(forKey: .from)!

    var frame = inView.bounds

    switch transitionType {
    case .presenting:

    toView.frame = frame.offsetBy(dx: frame.size.width, dy: 0)
    inView.insertSubview(toView, aboveSubview: fromView)

    UIView.animate(withDuration: transitionDuration(using: transitionContext),
    delay: 0,
    options: .curveLinear,
    animations: {

    //frame.origin.x = -frame.width
    toView.frame = frame

    }, completion: { finished in
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
    })
    case .dismissing:

    frame.origin.x = -frame.size.width
    toView.frame = frame

    inView.addSubview(toView)

    UIView.animate(withDuration: transitionDuration(using: transitionContext),
    delay: 0,
    options: .curveLinear,
    animations: {
    toView.frame = inView.bounds
    fromView.frame = CGRect(x: frame.width, y: 0, width: frame.width, height: frame.height)
    }, completion: { finished in
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
    })
    }
    }

    }

    class PresentationController: UIPresentationController {
    override var shouldRemovePresentersView: Bool { return true }
    }
  3. IamMarik created this gist Mar 9, 2020.
    43 changes: 43 additions & 0 deletions Customtransition.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@

    class MenuNavigationController: UINavigationController {
    var customTransitionDelegate = TransitionDelegate()

    weak var presentedController: UINavigationController?
    var interactionController: UIPercentDrivenInteractiveTransition?


    func presentNavigationController(_ controller: UINavigationController, animated: Bool) {
    controller.modalPresentationStyle = .custom
    controller.transitioningDelegate = self.customTransitionDelegate
    let panDown = UIPanGestureRecognizer(target: self, action: #selector(handleDissmiss(_:)))
    controller.view.addGestureRecognizer(panDown)
    self.present(controller, animated: animated) {
    self.presentedController = controller
    }
    }

    @objc func handleDissmiss(_ gesture: UIPanGestureRecognizer) {
    let translate = gesture.translation(in: gesture.view)
    let percent = translate.x / gesture.view!.bounds.size.width
    if gesture.state == .began {
    if gesture.location(in: gesture.view).x / gesture.view!.bounds.size.width < 0.3 {
    interactionController = UIPercentDrivenInteractiveTransition()
    customTransitionDelegate.interactionController = interactionController
    self.dismiss(animated: true, completion: nil)
    }
    } else if gesture.state == .changed {
    interactionController?.update(percent)
    } else if gesture.state == .ended || gesture.state == .cancelled {
    let velocity = gesture.velocity(in: gesture.view)
    print(velocity)
    print(percent)
    if percent > 0.5 || velocity.x > 500 {
    interactionController?.finish()
    } else {
    interactionController?.cancel()
    }
    interactionController = nil
    }
    }

    }