Skip to content

Instantly share code, notes, and snippets.

@alfian0
Created January 23, 2018 01:10
Show Gist options
  • Save alfian0/3fe77a81764f34b69cfead4a77b229ae to your computer and use it in GitHub Desktop.
Save alfian0/3fe77a81764f34b69cfead4a77b229ae to your computer and use it in GitHub Desktop.
import UIKit
class MenuTransition: NSObject, UIViewControllerAnimatedTransitioning {
private var state: TransitionState = .present
private typealias Screens = (from: UIViewController, to: UIViewController)
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return PresentationController(presentedViewController: presented, presenting: presenting)
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
let duration = transitionDuration(using: transitionContext)
let screens: Screens = (transitionContext.viewController(forKey: .from)!, transitionContext.viewController(forKey: .to)!)
switch state {
case .present:
present(duration: duration, container: container, screens: screens, transitionContext: transitionContext)
case .dismiss:
dismiss(duration: duration, container: container, screens: screens, transitionContext: transitionContext)
}
}
}
extension MenuTransition: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
state = .present
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
state = .dismiss
return self
}
}
extension MenuTransition {
private func present(duration: TimeInterval, container: UIView, screens: Screens, transitionContext: UIViewControllerContextTransitioning) {
container.insertSubview(screens.to.view, aboveSubview: screens.from.view)
screens.to.view.transform = CGAffineTransform(translationX: -container.bounds.width, y: 0)
UIView.animate(withDuration: duration, animations: {
screens.to.view.transform = CGAffineTransform.identity
}) { (_) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
private func dismiss(duration: TimeInterval, container: UIView, screens: Screens, transitionContext: UIViewControllerContextTransitioning) {
UIView.animate(withDuration: duration, animations: {
screens.from.view.transform = CGAffineTransform(translationX: -container.bounds.width, y: 0)
}) { (_) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
import UIKit
class PresentationController: UIPresentationController {
private var chrome: UIView = UIView()
override var frameOfPresentedViewInContainerView: CGRect {
return CGRect(x: 0, y: 0, width: containerView!.bounds.width-56, height: containerView!.bounds.height)
}
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
chrome.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
chrome.alpha = 0.0
chrome.addGestureRecognizer(
UITapGestureRecognizer(target: self, action: #selector(tapGesture(sender:)))
)
}
override func containerViewWillLayoutSubviews() {
chrome.frame = containerView!.bounds
presentedView?.frame = frameOfPresentedViewInContainerView
}
override func presentationTransitionWillBegin() {
containerView?.insertSubview(chrome, at: 0)
presentedViewController
.transitionCoordinator?
.animate(alongsideTransition: { (_) in
self.chrome.alpha = 1.0
}, completion: nil)
}
override func dismissalTransitionWillBegin() {
presentedViewController
.transitionCoordinator?
.animate(alongsideTransition: { (_) in
self.chrome.alpha = 0.0
}, completion: nil)
}
@objc private func tapGesture(sender: UIGestureRecognizer) {
presentedViewController.dismiss(animated: true, completion: nil)
}
}
@alfian0
Copy link
Author

alfian0 commented Feb 21, 2018

How to use

let menuTransition = MenuTransition()
let nv = UINavigationController(rootViewController: UIViewController())
nv.modalPresentationStyle = .custom
nv.transitionDelegate = menuTransition
present(nv, animated: true, completion: nil)

@alfian0
Copy link
Author

alfian0 commented Feb 21, 2018

simulator screen shot - iphone 5s - 2018-02-21 at 18 12 04

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment