Advertisement
thieumao

Slide Menu

Sep 7th, 2016
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 35.11 KB | None | 0 0
  1. //
  2. //  SlidingMenuController.swift
  3. //
  4. //  Created by Vũ Trung Thành on 10/9/15.
  5. //  Website: https://v2t.mobi
  6. //  Copyright © 2015 V2T Multimedia. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10.  
  11. public struct SlideMenuOptions {
  12.     public static var leftViewWidth: CGFloat = 270.0
  13.     public static var leftBezelWidth: CGFloat = 16.0
  14.     public static var contentViewScale: CGFloat = 0.96
  15.     public static var contentViewOpacity: CGFloat = 0.5
  16.     public static var shadowOpacity: CGFloat = 0.0
  17.     public static var shadowRadius: CGFloat = 0.0
  18.     public static var shadowOffset: CGSize = CGSizeMake(0,0)
  19.     public static var panFromBezel: Bool = true
  20.     public static var animationDuration: CGFloat = 0.4
  21.     public static var rightViewWidth: CGFloat = 270.0
  22.     public static var rightBezelWidth: CGFloat = 16.0
  23.     public static var rightPanFromBezel: Bool = true
  24.     public static var hideStatusBar: Bool = true
  25.     public static var pointOfNoReturnWidth: CGFloat = 44.0
  26.     public static var opacityViewBackgroundColor: UIColor = UIColor.blackColor()
  27. }
  28.  
  29. public class SlideMenuController: UIViewController, UIGestureRecognizerDelegate {
  30.    
  31.     public enum SlideAction {
  32.         case Open
  33.         case Close
  34.     }
  35.    
  36.     public enum TrackAction {
  37.         case TapOpen
  38.         case TapClose
  39.         case FlickOpen
  40.         case FlickClose
  41.     }
  42.    
  43.    
  44.     struct PanInfo {
  45.         var action: SlideAction
  46.         var shouldBounce: Bool
  47.         var velocity: CGFloat
  48.     }
  49.    
  50.     public var opacityView = UIView()
  51.     public var mainContainerView = UIView()
  52.     public var leftContainerView = UIView()
  53.     public var rightContainerView =  UIView()
  54.     public var mainViewController: UIViewController?
  55.     public var leftViewController: UIViewController?
  56.     public var leftPanGesture: UIPanGestureRecognizer?
  57.     public var leftTapGetsture: UITapGestureRecognizer?
  58.     public var rightViewController: UIViewController?
  59.     public var rightPanGesture: UIPanGestureRecognizer?
  60.     public var rightTapGesture: UITapGestureRecognizer?
  61.    
  62.     public required init?(coder aDecoder: NSCoder) {
  63.         super.init(coder: aDecoder)
  64.     }
  65.    
  66.     public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
  67.         super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
  68.     }
  69.    
  70.     public convenience init(mainViewController: UIViewController, leftMenuViewController: UIViewController) {
  71.         self.init()
  72.         self.mainViewController = mainViewController
  73.         leftViewController = leftMenuViewController
  74.         initView()
  75.     }
  76.    
  77.     public convenience init(mainViewController: UIViewController, rightMenuViewController: UIViewController) {
  78.         self.init()
  79.         self.mainViewController = mainViewController
  80.         rightViewController = rightMenuViewController
  81.         initView()
  82.     }
  83.    
  84.     public convenience init(mainViewController: UIViewController, leftMenuViewController: UIViewController, rightMenuViewController: UIViewController) {
  85.         self.init()
  86.         self.mainViewController = mainViewController
  87.         leftViewController = leftMenuViewController
  88.         rightViewController = rightMenuViewController
  89.         initView()
  90.     }
  91.    
  92.     deinit { }
  93.    
  94.     func initView() {
  95.         mainContainerView = UIView(frame: view.bounds)
  96.         mainContainerView.backgroundColor = UIColor.clearColor()
  97.         mainContainerView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
  98.         view.insertSubview(mainContainerView, atIndex: 0)
  99.        
  100.         var opacityframe: CGRect = view.bounds
  101.         let opacityOffset: CGFloat = 0
  102.         opacityframe.origin.y = opacityframe.origin.y + opacityOffset
  103.         opacityframe.size.height = opacityframe.size.height - opacityOffset
  104.         opacityView = UIView(frame: opacityframe)
  105.         opacityView.backgroundColor = SlideMenuOptions.opacityViewBackgroundColor
  106.         opacityView.autoresizingMask = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth]
  107.         opacityView.layer.opacity = 0.0
  108.         view.insertSubview(opacityView, atIndex: 1)
  109.        
  110.         var leftFrame: CGRect = view.bounds
  111.         leftFrame.size.width = SlideMenuOptions.leftViewWidth
  112.         leftFrame.origin.x = leftMinOrigin();
  113.         let leftOffset: CGFloat = 0
  114.         leftFrame.origin.y = leftFrame.origin.y + leftOffset
  115.         leftFrame.size.height = leftFrame.size.height - leftOffset
  116.         leftContainerView = UIView(frame: leftFrame)
  117.         leftContainerView.backgroundColor = UIColor.clearColor()
  118.         leftContainerView.autoresizingMask = UIViewAutoresizing.FlexibleHeight
  119.         view.insertSubview(leftContainerView, atIndex: 2)
  120.        
  121.         var rightFrame: CGRect = view.bounds
  122.         rightFrame.size.width = SlideMenuOptions.rightViewWidth
  123.         rightFrame.origin.x = rightMinOrigin()
  124.         let rightOffset: CGFloat = 0
  125.         rightFrame.origin.y = rightFrame.origin.y + rightOffset;
  126.         rightFrame.size.height = rightFrame.size.height - rightOffset
  127.         rightContainerView = UIView(frame: rightFrame)
  128.         rightContainerView.backgroundColor = UIColor.clearColor()
  129.         rightContainerView.autoresizingMask = UIViewAutoresizing.FlexibleHeight
  130.         view.insertSubview(rightContainerView, atIndex: 3)
  131.        
  132.         addLeftGestures()
  133.         addRightGestures()
  134.     }
  135.    
  136.     @available(iOS 8.0, *)
  137.     public override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
  138.         super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
  139.         mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
  140.         leftContainerView.hidden = true
  141.         rightContainerView.hidden = true
  142.        
  143.         coordinator.animateAlongsideTransition(nil, completion: { (context: UIViewControllerTransitionCoordinatorContext!) -> Void in
  144.             self.closeLeftNonAnimation()
  145.             self.closeRightNonAnimation()
  146.             self.leftContainerView.hidden = false
  147.             self.rightContainerView.hidden = false
  148.            
  149.             if self.leftPanGesture != nil && self.leftPanGesture != nil {
  150.                 self.removeLeftGestures()
  151.                 self.addLeftGestures()
  152.             }
  153.            
  154.             if self.rightPanGesture != nil && self.rightPanGesture != nil {
  155.                 self.removeRightGestures()
  156.                 self.addRightGestures()
  157.             }
  158.         })
  159.     }
  160.    
  161.     public override func viewDidLoad() {
  162.         super.viewDidLoad()
  163.         edgesForExtendedLayout = UIRectEdge.None
  164.     }
  165.    
  166.     public override func viewWillLayoutSubviews() {
  167.  
  168.         setUpViewController(mainContainerView, targetViewController: mainViewController)
  169.         setUpViewController(leftContainerView, targetViewController: leftViewController)
  170.         setUpViewController(rightContainerView, targetViewController: rightViewController)
  171.     }
  172.    
  173.     public override func openLeft() {
  174.         setOpenWindowLevel()
  175.        
  176.  
  177.         leftViewController?.beginAppearanceTransition(isLeftHidden(), animated: true)
  178.         openLeftWithVelocity(0.0)
  179.        
  180.         track(.TapOpen)
  181.     }
  182.    
  183.     public override func openRight() {
  184.         setOpenWindowLevel()
  185.        
  186.  
  187.         rightViewController?.beginAppearanceTransition(isRightHidden(), animated: true)
  188.         openRightWithVelocity(0.0)
  189.     }
  190.    
  191.     public override func closeLeft() {
  192.         leftViewController?.beginAppearanceTransition(isLeftHidden(), animated: true)
  193.         closeLeftWithVelocity(0.0)
  194.         setCloseWindowLebel()
  195.     }
  196.    
  197.     public override func closeRight() {
  198.         rightViewController?.beginAppearanceTransition(isRightHidden(), animated: true)
  199.         closeRightWithVelocity(0.0)
  200.         setCloseWindowLebel()
  201.     }
  202.    
  203.    
  204.     public func addLeftGestures() {
  205.        
  206.         if (leftViewController != nil) {
  207.             if leftPanGesture == nil {
  208.                 leftPanGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handleLeftPanGesture(_:)))
  209.                 leftPanGesture!.delegate = self
  210.                 view.addGestureRecognizer(leftPanGesture!)
  211.             }
  212.            
  213.             if leftTapGetsture == nil {
  214.                 leftTapGetsture = UITapGestureRecognizer(target: self, action: #selector(UIViewController.toggleLeft))
  215.                 leftTapGetsture!.delegate = self
  216.                 view.addGestureRecognizer(leftTapGetsture!)
  217.             }
  218.         }
  219.     }
  220.    
  221.     public func addRightGestures() {
  222.        
  223.         if (rightViewController != nil) {
  224.             if rightPanGesture == nil {
  225.                 rightPanGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handleRightPanGesture(_:)))
  226.                 rightPanGesture!.delegate = self
  227.                 view.addGestureRecognizer(rightPanGesture!)
  228.             }
  229.            
  230.             if rightTapGesture == nil {
  231.                 rightTapGesture = UITapGestureRecognizer(target: self, action: #selector(UIViewController.toggleRight))
  232.                 rightTapGesture!.delegate = self
  233.                 view.addGestureRecognizer(rightTapGesture!)
  234.             }
  235.         }
  236.     }
  237.    
  238.     public func removeLeftGestures() {
  239.        
  240.         if leftPanGesture != nil {
  241.             view.removeGestureRecognizer(leftPanGesture!)
  242.             leftPanGesture = nil
  243.         }
  244.        
  245.         if leftTapGetsture != nil {
  246.             view.removeGestureRecognizer(leftTapGetsture!)
  247.             leftTapGetsture = nil
  248.         }
  249.     }
  250.    
  251.     public func removeRightGestures() {
  252.        
  253.         if rightPanGesture != nil {
  254.             view.removeGestureRecognizer(rightPanGesture!)
  255.             rightPanGesture = nil
  256.         }
  257.        
  258.         if rightTapGesture != nil {
  259.             view.removeGestureRecognizer(rightTapGesture!)
  260.             rightTapGesture = nil
  261.         }
  262.     }
  263.    
  264.     public func isTagetViewController() -> Bool {
  265.         // Function to determine the target ViewController
  266.         // Please to override it if necessary
  267.         return true
  268.     }
  269.    
  270.     public func track(trackAction: TrackAction) {
  271.         // function is for tracking
  272.         // Please to override it if necessary
  273.     }
  274.    
  275.     struct LeftPanState {
  276.         static var frameAtStartOfPan: CGRect = CGRectZero
  277.         static var startPointOfPan: CGPoint = CGPointZero
  278.         static var wasOpenAtStartOfPan: Bool = false
  279.         static var wasHiddenAtStartOfPan: Bool = false
  280.     }
  281.    
  282.     func handleLeftPanGesture(panGesture: UIPanGestureRecognizer) {
  283.        
  284.         if !isTagetViewController() {
  285.             return
  286.         }
  287.        
  288.         if isRightOpen() {
  289.             return
  290.         }
  291.        
  292.         switch panGesture.state {
  293.         case UIGestureRecognizerState.Began:
  294.            
  295.             LeftPanState.frameAtStartOfPan = leftContainerView.frame
  296.             LeftPanState.startPointOfPan = panGesture.locationInView(view)
  297.             LeftPanState.wasOpenAtStartOfPan = isLeftOpen()
  298.             LeftPanState.wasHiddenAtStartOfPan = isLeftHidden()
  299.            
  300.             leftViewController?.beginAppearanceTransition(LeftPanState.wasHiddenAtStartOfPan, animated: true)
  301.             addShadowToView(leftContainerView)
  302.             setOpenWindowLevel()
  303.         case UIGestureRecognizerState.Changed:
  304.            
  305.             let translation: CGPoint = panGesture.translationInView(panGesture.view!)
  306.             leftContainerView.frame = applyLeftTranslation(translation, toFrame: LeftPanState.frameAtStartOfPan)
  307.             applyLeftOpacity()
  308.             applyLeftContentViewScale()
  309.         case UIGestureRecognizerState.Ended:
  310.            
  311.             let velocity:CGPoint = panGesture.velocityInView(panGesture.view)
  312.             let panInfo: PanInfo = panLeftResultInfoForVelocity(velocity)
  313.            
  314.             if panInfo.action == .Open {
  315.                 if !LeftPanState.wasHiddenAtStartOfPan {
  316.                     leftViewController?.beginAppearanceTransition(true, animated: true)
  317.                 }
  318.                 openLeftWithVelocity(panInfo.velocity)
  319.                 track(.FlickOpen)
  320.                
  321.             } else {
  322.                 if LeftPanState.wasHiddenAtStartOfPan {
  323.                     leftViewController?.beginAppearanceTransition(false, animated: true)
  324.                 }
  325.                 closeLeftWithVelocity(panInfo.velocity)
  326.                 setCloseWindowLebel()
  327.                
  328.                 track(.FlickClose)
  329.                
  330.             }
  331.         default:
  332.             break
  333.         }
  334.        
  335.     }
  336.    
  337.     struct RightPanState {
  338.         static var frameAtStartOfPan: CGRect = CGRectZero
  339.         static var startPointOfPan: CGPoint = CGPointZero
  340.         static var wasOpenAtStartOfPan: Bool = false
  341.         static var wasHiddenAtStartOfPan: Bool = false
  342.     }
  343.    
  344.     func handleRightPanGesture(panGesture: UIPanGestureRecognizer) {
  345.        
  346.         if !isTagetViewController() {
  347.             return
  348.         }
  349.        
  350.         if isLeftOpen() {
  351.             return
  352.         }
  353.        
  354.         switch panGesture.state {
  355.         case UIGestureRecognizerState.Began:
  356.            
  357.             RightPanState.frameAtStartOfPan = rightContainerView.frame
  358.             RightPanState.startPointOfPan = panGesture.locationInView(view)
  359.             RightPanState.wasOpenAtStartOfPan =  isRightOpen()
  360.             RightPanState.wasHiddenAtStartOfPan = isRightHidden()
  361.            
  362.             rightViewController?.beginAppearanceTransition(RightPanState.wasHiddenAtStartOfPan, animated: true)
  363.             addShadowToView(rightContainerView)
  364.             setOpenWindowLevel()
  365.         case UIGestureRecognizerState.Changed:
  366.            
  367.             let translation: CGPoint = panGesture.translationInView(panGesture.view!)
  368.             rightContainerView.frame = applyRightTranslation(translation, toFrame: RightPanState.frameAtStartOfPan)
  369.             applyRightOpacity()
  370.             applyRightContentViewScale()
  371.            
  372.         case UIGestureRecognizerState.Ended:
  373.            
  374.             let velocity: CGPoint = panGesture.velocityInView(panGesture.view)
  375.             let panInfo: PanInfo = panRightResultInfoForVelocity(velocity)
  376.            
  377.             if panInfo.action == .Open {
  378.                 if !RightPanState.wasHiddenAtStartOfPan {
  379.                     rightViewController?.beginAppearanceTransition(true, animated: true)
  380.                 }
  381.                 openRightWithVelocity(panInfo.velocity)
  382.             } else {
  383.                 if RightPanState.wasHiddenAtStartOfPan {
  384.                     rightViewController?.beginAppearanceTransition(false, animated: true)
  385.                 }
  386.                 closeRightWithVelocity(panInfo.velocity)
  387.                 setCloseWindowLebel()
  388.             }
  389.         default:
  390.             break
  391.         }
  392.     }
  393.    
  394.     public func openLeftWithVelocity(velocity: CGFloat) {
  395.         let xOrigin: CGFloat = leftContainerView.frame.origin.x
  396.         let finalXOrigin: CGFloat = 0.0
  397.        
  398.         var frame = leftContainerView.frame;
  399.         frame.origin.x = finalXOrigin;
  400.        
  401.         var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
  402.         if velocity != 0.0 {
  403.             duration = Double(fabs(xOrigin - finalXOrigin) / velocity)
  404.             duration = Double(fmax(0.1, fmin(1.0, duration)))
  405.         }
  406.        
  407.         addShadowToView(leftContainerView)
  408.        
  409.         UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
  410.             if let strongSelf = self {
  411.                 strongSelf.leftContainerView.frame = frame
  412.                 strongSelf.opacityView.layer.opacity = Float(SlideMenuOptions.contentViewOpacity)
  413.                 strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(SlideMenuOptions.contentViewScale, SlideMenuOptions.contentViewScale)
  414.             }
  415.             }) { [weak self](Bool) -> Void in
  416.                 if let strongSelf = self {
  417.                     strongSelf.disableContentInteraction()
  418.                     strongSelf.leftViewController?.endAppearanceTransition()
  419.                 }
  420.         }
  421.     }
  422.    
  423.     public func openRightWithVelocity(velocity: CGFloat) {
  424.         let xOrigin: CGFloat = rightContainerView.frame.origin.x
  425.        
  426.         //  CGFloat finalXOrigin = SlideMenuOptions.rightViewOverlapWidth;
  427.         let finalXOrigin: CGFloat = CGRectGetWidth(view.bounds) - rightContainerView.frame.size.width
  428.        
  429.         var frame = rightContainerView.frame
  430.         frame.origin.x = finalXOrigin
  431.        
  432.         var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
  433.         if velocity != 0.0 {
  434.             duration = Double(fabs(xOrigin - CGRectGetWidth(view.bounds)) / velocity)
  435.             duration = Double(fmax(0.1, fmin(1.0, duration)))
  436.         }
  437.        
  438.         addShadowToView(rightContainerView)
  439.        
  440.         UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
  441.             if let strongSelf = self {
  442.                 strongSelf.rightContainerView.frame = frame
  443.                 strongSelf.opacityView.layer.opacity = Float(SlideMenuOptions.contentViewOpacity)
  444.                 strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(SlideMenuOptions.contentViewScale, SlideMenuOptions.contentViewScale)
  445.             }
  446.             }) { [weak self](Bool) -> Void in
  447.                 if let strongSelf = self {
  448.                     strongSelf.disableContentInteraction()
  449.                     strongSelf.rightViewController?.endAppearanceTransition()
  450.                 }
  451.         }
  452.     }
  453.    
  454.     public func closeLeftWithVelocity(velocity: CGFloat) {
  455.        
  456.         let xOrigin: CGFloat = leftContainerView.frame.origin.x
  457.         let finalXOrigin: CGFloat = leftMinOrigin()
  458.        
  459.         var frame: CGRect = leftContainerView.frame;
  460.         frame.origin.x = finalXOrigin
  461.        
  462.         var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
  463.         if velocity != 0.0 {
  464.             duration = Double(fabs(xOrigin - finalXOrigin) / velocity)
  465.             duration = Double(fmax(0.1, fmin(1.0, duration)))
  466.         }
  467.        
  468.         UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
  469.             if let strongSelf = self {
  470.                 strongSelf.leftContainerView.frame = frame
  471.                 strongSelf.opacityView.layer.opacity = 0.0
  472.                 strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
  473.             }
  474.             }) { [weak self](Bool) -> Void in
  475.                 if let strongSelf = self {
  476.                     strongSelf.removeShadow(strongSelf.leftContainerView)
  477.                     strongSelf.enableContentInteraction()
  478.                     strongSelf.leftViewController?.endAppearanceTransition()
  479.                 }
  480.         }
  481.     }
  482.    
  483.    
  484.     public func closeRightWithVelocity(velocity: CGFloat) {
  485.        
  486.         let xOrigin: CGFloat = rightContainerView.frame.origin.x
  487.         let finalXOrigin: CGFloat = CGRectGetWidth(view.bounds)
  488.        
  489.         var frame: CGRect = rightContainerView.frame
  490.         frame.origin.x = finalXOrigin
  491.        
  492.         var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
  493.         if velocity != 0.0 {
  494.             duration = Double(fabs(xOrigin - CGRectGetWidth(view.bounds)) / velocity)
  495.             duration = Double(fmax(0.1, fmin(1.0, duration)))
  496.         }
  497.        
  498.         UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
  499.             if let strongSelf = self {
  500.                 strongSelf.rightContainerView.frame = frame
  501.                 strongSelf.opacityView.layer.opacity = 0.0
  502.                 strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
  503.             }
  504.             }) { [weak self](Bool) -> Void in
  505.                 if let strongSelf = self {
  506.                     strongSelf.removeShadow(strongSelf.rightContainerView)
  507.                     strongSelf.enableContentInteraction()
  508.                     strongSelf.rightViewController?.endAppearanceTransition()
  509.                 }
  510.         }
  511.     }
  512.    
  513.    
  514.     public override func toggleLeft() {
  515.         if isLeftOpen() {
  516.             closeLeft()
  517.             setCloseWindowLebel()
  518.            
  519.             track(.TapClose)
  520.         } else {
  521.             openLeft()
  522.         }
  523.     }
  524.    
  525.     public func isLeftOpen() -> Bool {
  526.         return leftContainerView.frame.origin.x == 0.0
  527.     }
  528.    
  529.     public func isLeftHidden() -> Bool {
  530.         return leftContainerView.frame.origin.x <= leftMinOrigin()
  531.     }
  532.    
  533.     public override func toggleRight() {
  534.         if isRightOpen() {
  535.             closeRight()
  536.             setCloseWindowLebel()
  537.         } else {
  538.             openRight()
  539.         }
  540.     }
  541.    
  542.     public func isRightOpen() -> Bool {
  543.         return rightContainerView.frame.origin.x == CGRectGetWidth(view.bounds) - rightContainerView.frame.size.width
  544.     }
  545.    
  546.     public func isRightHidden() -> Bool {
  547.         return rightContainerView.frame.origin.x >= CGRectGetWidth(view.bounds)
  548.     }
  549.    
  550.     public func changeMainViewController(mainViewController: UIViewController,  close: Bool) {
  551.        
  552.         removeViewController(self.mainViewController)
  553.         self.mainViewController = mainViewController
  554.         setUpViewController(mainContainerView, targetViewController: mainViewController)
  555.         if (close) {
  556.             closeLeft()
  557.             closeRight()
  558.         }
  559.     }
  560.    
  561.     public func changeLeftViewController(leftViewController: UIViewController, closeLeft:Bool) {
  562.        
  563.         removeViewController(self.leftViewController)
  564.         self.leftViewController = leftViewController
  565.         setUpViewController(leftContainerView, targetViewController: leftViewController)
  566.         if closeLeft {
  567.             self.closeLeft()
  568.         }
  569.     }
  570.    
  571.     public func changeRightViewController(rightViewController: UIViewController, closeRight:Bool) {
  572.         removeViewController(self.rightViewController)
  573.         self.rightViewController = rightViewController;
  574.         setUpViewController(rightContainerView, targetViewController: rightViewController)
  575.         if closeRight {
  576.             self.closeRight()
  577.         }
  578.     }
  579.    
  580.     private func leftMinOrigin() -> CGFloat {
  581.         return  -SlideMenuOptions.leftViewWidth
  582.     }
  583.    
  584.     private func rightMinOrigin() -> CGFloat {
  585.         return CGRectGetWidth(view.bounds)
  586.     }
  587.    
  588.    
  589.     private func panLeftResultInfoForVelocity(velocity: CGPoint) -> PanInfo {
  590.        
  591.         let thresholdVelocity: CGFloat = 1000.0
  592.         let pointOfNoReturn: CGFloat = CGFloat(floor(leftMinOrigin())) + SlideMenuOptions.pointOfNoReturnWidth
  593.         let leftOrigin: CGFloat = leftContainerView.frame.origin.x
  594.        
  595.         var panInfo: PanInfo = PanInfo(action: .Close, shouldBounce: false, velocity: 0.0)
  596.        
  597.         panInfo.action = leftOrigin <= pointOfNoReturn ? .Close : .Open;
  598.        
  599.         if velocity.x >= thresholdVelocity {
  600.             panInfo.action = .Open
  601.             panInfo.velocity = velocity.x
  602.         } else if velocity.x <= (-1.0 * thresholdVelocity) {
  603.             panInfo.action = .Close
  604.             panInfo.velocity = velocity.x
  605.         }
  606.        
  607.         return panInfo
  608.     }
  609.    
  610.     private func panRightResultInfoForVelocity(velocity: CGPoint) -> PanInfo {
  611.        
  612.         let thresholdVelocity: CGFloat = -1000.0
  613.         let pointOfNoReturn: CGFloat = CGFloat(floor(CGRectGetWidth(view.bounds)) - SlideMenuOptions.pointOfNoReturnWidth)
  614.         let rightOrigin: CGFloat = rightContainerView.frame.origin.x
  615.        
  616.         var panInfo: PanInfo = PanInfo(action: .Close, shouldBounce: false, velocity: 0.0)
  617.        
  618.         panInfo.action = rightOrigin >= pointOfNoReturn ? .Close : .Open
  619.        
  620.         if velocity.x <= thresholdVelocity {
  621.             panInfo.action = .Open
  622.             panInfo.velocity = velocity.x
  623.         } else if (velocity.x >= (-1.0 * thresholdVelocity)) {
  624.             panInfo.action = .Close
  625.             panInfo.velocity = velocity.x
  626.         }
  627.        
  628.         return panInfo
  629.     }
  630.    
  631.     private func applyLeftTranslation(translation: CGPoint, toFrame:CGRect) -> CGRect {
  632.        
  633.         var newOrigin: CGFloat = toFrame.origin.x
  634.         newOrigin += translation.x
  635.        
  636.         let minOrigin: CGFloat = leftMinOrigin()
  637.         let maxOrigin: CGFloat = 0.0
  638.         var newFrame: CGRect = toFrame
  639.        
  640.         if newOrigin < minOrigin {
  641.             newOrigin = minOrigin
  642.         } else if newOrigin > maxOrigin {
  643.             newOrigin = maxOrigin
  644.         }
  645.        
  646.         newFrame.origin.x = newOrigin
  647.         return newFrame
  648.     }
  649.    
  650.     private func applyRightTranslation(translation: CGPoint, toFrame: CGRect) -> CGRect {
  651.        
  652.         var  newOrigin: CGFloat = toFrame.origin.x
  653.         newOrigin += translation.x
  654.        
  655.         let minOrigin: CGFloat = rightMinOrigin()
  656.         let maxOrigin: CGFloat = rightMinOrigin() - rightContainerView.frame.size.width
  657.         var newFrame: CGRect = toFrame
  658.        
  659.         if newOrigin > minOrigin {
  660.             newOrigin = minOrigin
  661.         } else if newOrigin < maxOrigin {
  662.             newOrigin = maxOrigin
  663.         }
  664.        
  665.         newFrame.origin.x = newOrigin
  666.         return newFrame
  667.     }
  668.    
  669.     private func getOpenedLeftRatio() -> CGFloat {
  670.        
  671.         let width: CGFloat = leftContainerView.frame.size.width
  672.         let currentPosition: CGFloat = leftContainerView.frame.origin.x - leftMinOrigin()
  673.         return currentPosition / width
  674.     }
  675.    
  676.     private func getOpenedRightRatio() -> CGFloat {
  677.        
  678.         let width: CGFloat = rightContainerView.frame.size.width
  679.         let currentPosition: CGFloat = rightContainerView.frame.origin.x
  680.         return -(currentPosition - CGRectGetWidth(view.bounds)) / width
  681.     }
  682.    
  683.     private func applyLeftOpacity() {
  684.        
  685.         let openedLeftRatio: CGFloat = getOpenedLeftRatio()
  686.         let opacity: CGFloat = SlideMenuOptions.contentViewOpacity * openedLeftRatio
  687.         opacityView.layer.opacity = Float(opacity)
  688.     }
  689.    
  690.    
  691.     private func applyRightOpacity() {
  692.         let openedRightRatio: CGFloat = getOpenedRightRatio()
  693.         let opacity: CGFloat = SlideMenuOptions.contentViewOpacity * openedRightRatio
  694.         opacityView.layer.opacity = Float(opacity)
  695.     }
  696.    
  697.     private func applyLeftContentViewScale() {
  698.         let openedLeftRatio: CGFloat = getOpenedLeftRatio()
  699.         let scale: CGFloat = 1.0 - ((1.0 - SlideMenuOptions.contentViewScale) * openedLeftRatio);
  700.         mainContainerView.transform = CGAffineTransformMakeScale(scale, scale)
  701.     }
  702.    
  703.     private func applyRightContentViewScale() {
  704.         let openedRightRatio: CGFloat = getOpenedRightRatio()
  705.         let scale: CGFloat = 1.0 - ((1.0 - SlideMenuOptions.contentViewScale) * openedRightRatio)
  706.         mainContainerView.transform = CGAffineTransformMakeScale(scale, scale)
  707.     }
  708.    
  709.     private func addShadowToView(targetContainerView: UIView) {
  710.         targetContainerView.layer.masksToBounds = false
  711.         targetContainerView.layer.shadowOffset = SlideMenuOptions.shadowOffset
  712.         targetContainerView.layer.shadowOpacity = Float(SlideMenuOptions.shadowOpacity)
  713.         targetContainerView.layer.shadowRadius = SlideMenuOptions.shadowRadius
  714.         targetContainerView.layer.shadowPath = UIBezierPath(rect: targetContainerView.bounds).CGPath
  715.     }
  716.    
  717.     private func removeShadow(targetContainerView: UIView) {
  718.         targetContainerView.layer.masksToBounds = true
  719.         mainContainerView.layer.opacity = 1.0
  720.     }
  721.    
  722.     private func removeContentOpacity() {
  723.         opacityView.layer.opacity = 0.0
  724.     }
  725.    
  726.    
  727.     private func addContentOpacity() {
  728.         opacityView.layer.opacity = Float(SlideMenuOptions.contentViewOpacity)
  729.     }
  730.    
  731.     private func disableContentInteraction() {
  732.         mainContainerView.userInteractionEnabled = false
  733.     }
  734.    
  735.     private func enableContentInteraction() {
  736.         mainContainerView.userInteractionEnabled = true
  737.     }
  738.    
  739.     private func setOpenWindowLevel() {
  740.         if (SlideMenuOptions.hideStatusBar) {
  741.             dispatch_async(dispatch_get_main_queue(), {
  742.                 if let window = UIApplication.sharedApplication().keyWindow {
  743.                     window.windowLevel = UIWindowLevelStatusBar + 1
  744.                 }
  745.             })
  746.         }
  747.     }
  748.    
  749.     private func setCloseWindowLebel() {
  750.         if (SlideMenuOptions.hideStatusBar) {
  751.             dispatch_async(dispatch_get_main_queue(), {
  752.                 if let window = UIApplication.sharedApplication().keyWindow {
  753.                     window.windowLevel = UIWindowLevelNormal
  754.                 }
  755.             })
  756.         }
  757.     }
  758.    
  759.     private func setUpViewController(targetView: UIView, targetViewController: UIViewController?) {
  760.         if let viewController = targetViewController {
  761.             addChildViewController(viewController)
  762.             viewController.view.frame = targetView.bounds
  763.             targetView.addSubview(viewController.view)
  764.             viewController.didMoveToParentViewController(self)
  765.         }
  766.     }
  767.    
  768.    
  769.     private func removeViewController(viewController: UIViewController?) {
  770.         if let _viewController = viewController {
  771.             _viewController.willMoveToParentViewController(nil)
  772.             _viewController.view.removeFromSuperview()
  773.             _viewController.removeFromParentViewController()
  774.         }
  775.     }
  776.    
  777.     public func closeLeftNonAnimation(){
  778.         setCloseWindowLebel()
  779.         let finalXOrigin: CGFloat = leftMinOrigin()
  780.         var frame: CGRect = leftContainerView.frame;
  781.         frame.origin.x = finalXOrigin
  782.         leftContainerView.frame = frame
  783.         opacityView.layer.opacity = 0.0
  784.         mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
  785.         removeShadow(leftContainerView)
  786.         enableContentInteraction()
  787.     }
  788.    
  789.     public func closeRightNonAnimation(){
  790.         setCloseWindowLebel()
  791.         let finalXOrigin: CGFloat = CGRectGetWidth(view.bounds)
  792.         var frame: CGRect = rightContainerView.frame
  793.         frame.origin.x = finalXOrigin
  794.         rightContainerView.frame = frame
  795.         opacityView.layer.opacity = 0.0
  796.         mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
  797.         removeShadow(rightContainerView)
  798.         enableContentInteraction()
  799.     }
  800.    
  801.     //pragma mark – UIGestureRecognizerDelegate
  802.     public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
  803.        
  804.         let point: CGPoint = touch.locationInView(view)
  805.        
  806.         if gestureRecognizer == leftPanGesture {
  807.             return slideLeftForGestureRecognizer(gestureRecognizer, point: point)
  808.         } else if gestureRecognizer == rightPanGesture {
  809.             return slideRightViewForGestureRecognizer(gestureRecognizer, withTouchPoint: point)
  810.         } else if gestureRecognizer == leftTapGetsture {
  811.             return isLeftOpen() && !isPointContainedWithinLeftRect(point)
  812.         } else if gestureRecognizer == rightTapGesture {
  813.             return isRightOpen() && !isPointContainedWithinRightRect(point)
  814.         }
  815.        
  816.         return true
  817.     }
  818.    
  819.     private func slideLeftForGestureRecognizer( gesture: UIGestureRecognizer, point:CGPoint) -> Bool{
  820.         return isLeftOpen() || SlideMenuOptions.panFromBezel && isLeftPointContainedWithinBezelRect(point)
  821.     }
  822.    
  823.     private func isLeftPointContainedWithinBezelRect(point: CGPoint) -> Bool{
  824.         var leftBezelRect: CGRect = CGRectZero
  825.         var tempRect: CGRect = CGRectZero
  826.         let bezelWidth: CGFloat = SlideMenuOptions.leftBezelWidth
  827.        
  828.         CGRectDivide(view.bounds, &leftBezelRect, &tempRect, bezelWidth, CGRectEdge.MinXEdge)
  829.         return CGRectContainsPoint(leftBezelRect, point)
  830.     }
  831.    
  832.     private func isPointContainedWithinLeftRect(point: CGPoint) -> Bool {
  833.         return CGRectContainsPoint(leftContainerView.frame, point)
  834.     }
  835.    
  836.    
  837.    
  838.     private func slideRightViewForGestureRecognizer(gesture: UIGestureRecognizer, withTouchPoint point: CGPoint) -> Bool {
  839.         return isRightOpen() || SlideMenuOptions.rightPanFromBezel && isRightPointContainedWithinBezelRect(point)
  840.     }
  841.    
  842.     private func isRightPointContainedWithinBezelRect(point: CGPoint) -> Bool {
  843.         var rightBezelRect: CGRect = CGRectZero
  844.         var tempRect: CGRect = CGRectZero
  845.         let bezelWidth: CGFloat = CGRectGetWidth(view.bounds) - SlideMenuOptions.rightBezelWidth
  846.        
  847.         CGRectDivide(view.bounds, &tempRect, &rightBezelRect, bezelWidth, CGRectEdge.MinXEdge)
  848.        
  849.         return CGRectContainsPoint(rightBezelRect, point)
  850.     }
  851.    
  852.     private func isPointContainedWithinRightRect(point: CGPoint) -> Bool {
  853.         return CGRectContainsPoint(rightContainerView.frame, point)
  854.     }
  855.    
  856. }
  857.  
  858.  
  859. extension UIViewController {
  860.    
  861.     public func slideMenuController() -> SlideMenuController? {
  862.         var viewController: UIViewController? = self
  863.         while viewController != nil {
  864.             if viewController is SlideMenuController {
  865.                 return viewController as? SlideMenuController
  866.             }
  867.             viewController = viewController?.parentViewController
  868.         }
  869.         return nil;
  870.     }
  871.    
  872.     public func addLeftBarButtonWithImage(buttonImage: UIImage) {
  873.         let leftButton: UIBarButtonItem = UIBarButtonItem(image: buttonImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(UIViewController.toggleLeft))
  874.         navigationItem.leftBarButtonItem = leftButton;
  875.     }
  876.    
  877.     public func addRightBarButtonWithImage(buttonImage: UIImage) {
  878.         let rightButton: UIBarButtonItem = UIBarButtonItem(image: buttonImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(UIViewController.toggleRight))
  879.         navigationItem.rightBarButtonItem = rightButton;
  880.     }
  881.    
  882.     public func toggleLeft() {
  883.         slideMenuController()?.toggleLeft()
  884.     }
  885.    
  886.     public func toggleRight() {
  887.         slideMenuController()?.toggleRight()
  888.     }
  889.    
  890.     public func openLeft() {
  891.         slideMenuController()?.openLeft()
  892.     }
  893.    
  894.     public func openRight() {
  895.         slideMenuController()?.openRight()    }
  896.    
  897.     public func closeLeft() {
  898.         slideMenuController()?.closeLeft()
  899.     }
  900.    
  901.     public func closeRight() {
  902.         slideMenuController()?.closeRight()
  903.     }
  904.    
  905.     // Please specify if you want menu gesuture give priority to than targetScrollView
  906.     public func addPriorityToMenuGesuture(targetScrollView: UIScrollView) {
  907.         guard let slideControlelr = slideMenuController(), let recognizers = slideControlelr.view.gestureRecognizers else {
  908.             return
  909.         }
  910.         for recognizer in recognizers where recognizer is UIPanGestureRecognizer {
  911.             targetScrollView.panGestureRecognizer.requireGestureRecognizerToFail(recognizer)
  912.         }
  913.     }
  914. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement