|
@@ -1,1051 +0,0 @@
|
|
|
-//
|
|
|
|
|
-// SlideMenuController.swift
|
|
|
|
|
-// Gasteizko Margolariak
|
|
|
|
|
-//
|
|
|
|
|
-// Created by Inigo Valentin on 2016-08-23
|
|
|
|
|
-// Copyright © 2016 Inigo Valentin. All rights reserved.
|
|
|
|
|
-//
|
|
|
|
|
-// Based on the work of Yuji Hato.
|
|
|
|
|
-//
|
|
|
|
|
-
|
|
|
|
|
-import Foundation
|
|
|
|
|
-import UIKit
|
|
|
|
|
-
|
|
|
|
|
-@objc public protocol SlideMenuControllerDelegate {
|
|
|
|
|
- optional func leftWillOpen()
|
|
|
|
|
- optional func leftDidOpen()
|
|
|
|
|
- optional func leftWillClose()
|
|
|
|
|
- optional func leftDidClose()
|
|
|
|
|
- optional func rightWillOpen()
|
|
|
|
|
- optional func rightDidOpen()
|
|
|
|
|
- optional func rightWillClose()
|
|
|
|
|
- optional func rightDidClose()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-public struct SlideMenuOptions {
|
|
|
|
|
- public static var leftViewWidth: CGFloat = 270.0
|
|
|
|
|
- public static var leftBezelWidth: CGFloat? = 16.0
|
|
|
|
|
- public static var contentViewScale: CGFloat = 0.96
|
|
|
|
|
- public static var contentViewOpacity: CGFloat = 0.5
|
|
|
|
|
- public static var contentViewDrag: Bool = false
|
|
|
|
|
- public static var shadowOpacity: CGFloat = 0.0
|
|
|
|
|
- public static var shadowRadius: CGFloat = 0.0
|
|
|
|
|
- public static var shadowOffset: CGSize = CGSizeMake(0,0)
|
|
|
|
|
- public static var panFromBezel: Bool = true
|
|
|
|
|
- public static var animationDuration: CGFloat = 0.4
|
|
|
|
|
- public static var rightViewWidth: CGFloat = 270.0
|
|
|
|
|
- public static var rightBezelWidth: CGFloat? = 16.0
|
|
|
|
|
- public static var rightPanFromBezel: Bool = true
|
|
|
|
|
- public static var hideStatusBar: Bool = true
|
|
|
|
|
- public static var pointOfNoReturnWidth: CGFloat = 44.0
|
|
|
|
|
- public static var simultaneousGestureRecognizers: Bool = true
|
|
|
|
|
- public static var opacityViewBackgroundColor: UIColor = UIColor.blackColor()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-public class SlideMenuController: UIViewController, UIGestureRecognizerDelegate {
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public enum SlideAction {
|
|
|
|
|
- case Open
|
|
|
|
|
- case Close
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public enum TrackAction {
|
|
|
|
|
- case LeftTapOpen
|
|
|
|
|
- case LeftTapClose
|
|
|
|
|
- case LeftFlickOpen
|
|
|
|
|
- case LeftFlickClose
|
|
|
|
|
- case RightTapOpen
|
|
|
|
|
- case RightTapClose
|
|
|
|
|
- case RightFlickOpen
|
|
|
|
|
- case RightFlickClose
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- struct PanInfo {
|
|
|
|
|
- var action: SlideAction
|
|
|
|
|
- var shouldBounce: Bool
|
|
|
|
|
- var velocity: CGFloat
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public weak var delegate: SlideMenuControllerDelegate?
|
|
|
|
|
-
|
|
|
|
|
- public var opacityView = UIView()
|
|
|
|
|
- public var mainContainerView = UIView()
|
|
|
|
|
- public var leftContainerView = UIView()
|
|
|
|
|
- public var rightContainerView = UIView()
|
|
|
|
|
- public var mainViewController: UIViewController?
|
|
|
|
|
- public var leftViewController: UIViewController?
|
|
|
|
|
- public var leftPanGesture: UIPanGestureRecognizer?
|
|
|
|
|
- public var leftTapGesture: UITapGestureRecognizer?
|
|
|
|
|
- public var rightViewController: UIViewController?
|
|
|
|
|
- public var rightPanGesture: UIPanGestureRecognizer?
|
|
|
|
|
- public var rightTapGesture: UITapGestureRecognizer?
|
|
|
|
|
-
|
|
|
|
|
- public required init?(coder aDecoder: NSCoder) {
|
|
|
|
|
- super.init(coder: aDecoder)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
|
|
|
|
|
- super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public convenience init(mainViewController: UIViewController) {
|
|
|
|
|
- self.init()
|
|
|
|
|
- self.mainViewController = mainViewController
|
|
|
|
|
- //leftViewController = leftMenuViewController
|
|
|
|
|
- initView()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public convenience init(mainViewController: UIViewController, leftMenuViewController: UIViewController, rightMenuViewController: UIViewController) {
|
|
|
|
|
- self.init()
|
|
|
|
|
- self.mainViewController = mainViewController
|
|
|
|
|
- leftViewController = leftMenuViewController
|
|
|
|
|
- initView()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func awakeFromNib() {
|
|
|
|
|
- initView()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- deinit { }
|
|
|
|
|
-
|
|
|
|
|
- public func initView() {
|
|
|
|
|
- mainContainerView = UIView(frame: view.bounds)
|
|
|
|
|
- mainContainerView.backgroundColor = UIColor.clearColor()
|
|
|
|
|
- mainContainerView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
|
|
|
|
|
- view.insertSubview(mainContainerView, atIndex: 0)
|
|
|
|
|
-
|
|
|
|
|
- var opacityframe: CGRect = view.bounds
|
|
|
|
|
- let opacityOffset: CGFloat = 0
|
|
|
|
|
- opacityframe.origin.y = opacityframe.origin.y + opacityOffset
|
|
|
|
|
- opacityframe.size.height = opacityframe.size.height - opacityOffset
|
|
|
|
|
- opacityView = UIView(frame: opacityframe)
|
|
|
|
|
- opacityView.backgroundColor = SlideMenuOptions.opacityViewBackgroundColor
|
|
|
|
|
- opacityView.autoresizingMask = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth]
|
|
|
|
|
- opacityView.layer.opacity = 0.0
|
|
|
|
|
- view.insertSubview(opacityView, atIndex: 1)
|
|
|
|
|
-
|
|
|
|
|
- if leftViewController != nil {
|
|
|
|
|
- var leftFrame: CGRect = view.bounds
|
|
|
|
|
- leftFrame.size.width = SlideMenuOptions.leftViewWidth
|
|
|
|
|
- leftFrame.origin.x = leftMinOrigin();
|
|
|
|
|
- let leftOffset: CGFloat = 0
|
|
|
|
|
- leftFrame.origin.y = leftFrame.origin.y + leftOffset
|
|
|
|
|
- leftFrame.size.height = leftFrame.size.height - leftOffset
|
|
|
|
|
- leftContainerView = UIView(frame: leftFrame)
|
|
|
|
|
- leftContainerView.backgroundColor = UIColor.clearColor()
|
|
|
|
|
- leftContainerView.autoresizingMask = UIViewAutoresizing.FlexibleHeight
|
|
|
|
|
- view.insertSubview(leftContainerView, atIndex: 2)
|
|
|
|
|
- addLeftGestures()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
|
|
|
|
|
- super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
|
|
|
|
|
- mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
|
|
|
|
|
- leftContainerView.hidden = true
|
|
|
|
|
- rightContainerView.hidden = true
|
|
|
|
|
-
|
|
|
|
|
- coordinator.animateAlongsideTransition(nil, completion: { (context: UIViewControllerTransitionCoordinatorContext!) -> Void in
|
|
|
|
|
- self.closeLeftNonAnimation()
|
|
|
|
|
- self.closeRightNonAnimation()
|
|
|
|
|
- self.leftContainerView.hidden = false
|
|
|
|
|
- self.rightContainerView.hidden = false
|
|
|
|
|
-
|
|
|
|
|
- if self.leftPanGesture != nil && self.leftPanGesture != nil {
|
|
|
|
|
- self.removeLeftGestures()
|
|
|
|
|
- self.addLeftGestures()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if self.rightPanGesture != nil && self.rightPanGesture != nil {
|
|
|
|
|
- self.removeRightGestures()
|
|
|
|
|
- self.addRightGestures()
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func viewDidLoad() {
|
|
|
|
|
- super.viewDidLoad()
|
|
|
|
|
- edgesForExtendedLayout = UIRectEdge.None
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
|
|
|
|
|
- if let mainController = self.mainViewController{
|
|
|
|
|
- return mainController.supportedInterfaceOrientations()
|
|
|
|
|
- }
|
|
|
|
|
- return UIInterfaceOrientationMask.All
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func shouldAutorotate() -> Bool {
|
|
|
|
|
- return mainViewController?.shouldAutorotate() ?? false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func viewWillLayoutSubviews() {
|
|
|
|
|
- // topLayoutGuideの値が確定するこのタイミングで各種ViewControllerをセットする
|
|
|
|
|
- setUpViewController(mainContainerView, targetViewController: mainViewController)
|
|
|
|
|
- setUpViewController(leftContainerView, targetViewController: leftViewController)
|
|
|
|
|
- setUpViewController(rightContainerView, targetViewController: rightViewController)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func openLeft() {
|
|
|
|
|
- guard let _ = leftViewController else { // If leftViewController is nil, then return
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- self.delegate?.leftWillOpen?()
|
|
|
|
|
-
|
|
|
|
|
- setOpenWindowLevel()
|
|
|
|
|
- // for call viewWillAppear of leftViewController
|
|
|
|
|
- leftViewController?.beginAppearanceTransition(isLeftHidden(), animated: true)
|
|
|
|
|
- openLeftWithVelocity(0.0)
|
|
|
|
|
-
|
|
|
|
|
- track(.LeftTapOpen)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func openRight() {
|
|
|
|
|
- guard let _ = rightViewController else { // If rightViewController is nil, then return
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- self.delegate?.rightWillOpen?()
|
|
|
|
|
-
|
|
|
|
|
- setOpenWindowLevel()
|
|
|
|
|
- rightViewController?.beginAppearanceTransition(isRightHidden(), animated: true)
|
|
|
|
|
- openRightWithVelocity(0.0)
|
|
|
|
|
-
|
|
|
|
|
- track(.RightTapOpen)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func closeLeft() {
|
|
|
|
|
- guard let _ = leftViewController else { // If leftViewController is nil, then return
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- self.delegate?.leftWillClose?()
|
|
|
|
|
-
|
|
|
|
|
- leftViewController?.beginAppearanceTransition(isLeftHidden(), animated: true)
|
|
|
|
|
- closeLeftWithVelocity(0.0)
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func closeRight() {
|
|
|
|
|
- guard let _ = rightViewController else { // If rightViewController is nil, then return
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- self.delegate?.rightWillClose?()
|
|
|
|
|
-
|
|
|
|
|
- rightViewController?.beginAppearanceTransition(isRightHidden(), animated: true)
|
|
|
|
|
- closeRightWithVelocity(0.0)
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public func addLeftGestures() {
|
|
|
|
|
-
|
|
|
|
|
- if (leftViewController != nil) {
|
|
|
|
|
- if leftPanGesture == nil {
|
|
|
|
|
- leftPanGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handleLeftPanGesture(_:)))
|
|
|
|
|
- leftPanGesture!.delegate = self
|
|
|
|
|
- view.addGestureRecognizer(leftPanGesture!)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if leftTapGesture == nil {
|
|
|
|
|
- leftTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.toggleLeft))
|
|
|
|
|
- leftTapGesture!.delegate = self
|
|
|
|
|
- view.addGestureRecognizer(leftTapGesture!)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func addRightGestures() {
|
|
|
|
|
-
|
|
|
|
|
- if (rightViewController != nil) {
|
|
|
|
|
- if rightPanGesture == nil {
|
|
|
|
|
- rightPanGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handleRightPanGesture(_:)))
|
|
|
|
|
- rightPanGesture!.delegate = self
|
|
|
|
|
- view.addGestureRecognizer(rightPanGesture!)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if rightTapGesture == nil {
|
|
|
|
|
- rightTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.toggleRight))
|
|
|
|
|
- rightTapGesture!.delegate = self
|
|
|
|
|
- view.addGestureRecognizer(rightTapGesture!)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func removeLeftGestures() {
|
|
|
|
|
-
|
|
|
|
|
- if leftPanGesture != nil {
|
|
|
|
|
- view.removeGestureRecognizer(leftPanGesture!)
|
|
|
|
|
- leftPanGesture = nil
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if leftTapGesture != nil {
|
|
|
|
|
- view.removeGestureRecognizer(leftTapGesture!)
|
|
|
|
|
- leftTapGesture = nil
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func removeRightGestures() {
|
|
|
|
|
-
|
|
|
|
|
- if rightPanGesture != nil {
|
|
|
|
|
- view.removeGestureRecognizer(rightPanGesture!)
|
|
|
|
|
- rightPanGesture = nil
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if rightTapGesture != nil {
|
|
|
|
|
- view.removeGestureRecognizer(rightTapGesture!)
|
|
|
|
|
- rightTapGesture = nil
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func isTagetViewController() -> Bool {
|
|
|
|
|
- // Function to determine the target ViewController
|
|
|
|
|
- // Please to override it if necessary
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func track(trackAction: TrackAction) {
|
|
|
|
|
- // function is for tracking
|
|
|
|
|
- // Please to override it if necessary
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- struct LeftPanState {
|
|
|
|
|
- static var frameAtStartOfPan: CGRect = CGRectZero
|
|
|
|
|
- static var startPointOfPan: CGPoint = CGPointZero
|
|
|
|
|
- static var wasOpenAtStartOfPan: Bool = false
|
|
|
|
|
- static var wasHiddenAtStartOfPan: Bool = false
|
|
|
|
|
- static var lastState : UIGestureRecognizerState = .Ended
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- func handleLeftPanGesture(panGesture: UIPanGestureRecognizer) {
|
|
|
|
|
-
|
|
|
|
|
- if !isTagetViewController() {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if isRightOpen() {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch panGesture.state {
|
|
|
|
|
- case UIGestureRecognizerState.Began:
|
|
|
|
|
- if LeftPanState.lastState != .Ended && LeftPanState.lastState != .Cancelled && LeftPanState.lastState != .Failed {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if isLeftHidden() {
|
|
|
|
|
- self.delegate?.leftWillOpen?()
|
|
|
|
|
- } else {
|
|
|
|
|
- self.delegate?.leftWillClose?()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- LeftPanState.frameAtStartOfPan = leftContainerView.frame
|
|
|
|
|
- LeftPanState.startPointOfPan = panGesture.locationInView(view)
|
|
|
|
|
- LeftPanState.wasOpenAtStartOfPan = isLeftOpen()
|
|
|
|
|
- LeftPanState.wasHiddenAtStartOfPan = isLeftHidden()
|
|
|
|
|
-
|
|
|
|
|
- leftViewController?.beginAppearanceTransition(LeftPanState.wasHiddenAtStartOfPan, animated: true)
|
|
|
|
|
- addShadowToView(leftContainerView)
|
|
|
|
|
- setOpenWindowLevel()
|
|
|
|
|
- case UIGestureRecognizerState.Changed:
|
|
|
|
|
- if LeftPanState.lastState != .Began && LeftPanState.lastState != .Changed {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let translation: CGPoint = panGesture.translationInView(panGesture.view!)
|
|
|
|
|
- leftContainerView.frame = applyLeftTranslation(translation, toFrame: LeftPanState.frameAtStartOfPan)
|
|
|
|
|
- applyLeftOpacity()
|
|
|
|
|
- applyLeftContentViewScale()
|
|
|
|
|
- case UIGestureRecognizerState.Ended, UIGestureRecognizerState.Cancelled:
|
|
|
|
|
- if LeftPanState.lastState != .Changed {
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let velocity:CGPoint = panGesture.velocityInView(panGesture.view)
|
|
|
|
|
- let panInfo: PanInfo = panLeftResultInfoForVelocity(velocity)
|
|
|
|
|
-
|
|
|
|
|
- if panInfo.action == .Open {
|
|
|
|
|
- if !LeftPanState.wasHiddenAtStartOfPan {
|
|
|
|
|
- leftViewController?.beginAppearanceTransition(true, animated: true)
|
|
|
|
|
- }
|
|
|
|
|
- openLeftWithVelocity(panInfo.velocity)
|
|
|
|
|
-
|
|
|
|
|
- track(.LeftFlickOpen)
|
|
|
|
|
- } else {
|
|
|
|
|
- if LeftPanState.wasHiddenAtStartOfPan {
|
|
|
|
|
- leftViewController?.beginAppearanceTransition(false, animated: true)
|
|
|
|
|
- }
|
|
|
|
|
- closeLeftWithVelocity(panInfo.velocity)
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
-
|
|
|
|
|
- track(.LeftFlickClose)
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- case UIGestureRecognizerState.Failed, UIGestureRecognizerState.Possible:
|
|
|
|
|
- break
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- LeftPanState.lastState = panGesture.state
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- struct RightPanState {
|
|
|
|
|
- static var frameAtStartOfPan: CGRect = CGRectZero
|
|
|
|
|
- static var startPointOfPan: CGPoint = CGPointZero
|
|
|
|
|
- static var wasOpenAtStartOfPan: Bool = false
|
|
|
|
|
- static var wasHiddenAtStartOfPan: Bool = false
|
|
|
|
|
- static var lastState : UIGestureRecognizerState = .Ended
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- func handleRightPanGesture(panGesture: UIPanGestureRecognizer) {
|
|
|
|
|
-
|
|
|
|
|
- if !isTagetViewController() {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if isLeftOpen() {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch panGesture.state {
|
|
|
|
|
- case UIGestureRecognizerState.Began:
|
|
|
|
|
- if RightPanState.lastState != .Ended && RightPanState.lastState != .Cancelled && RightPanState.lastState != .Failed {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if isRightHidden() {
|
|
|
|
|
- self.delegate?.rightWillOpen?()
|
|
|
|
|
- } else {
|
|
|
|
|
- self.delegate?.rightWillClose?()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- RightPanState.frameAtStartOfPan = rightContainerView.frame
|
|
|
|
|
- RightPanState.startPointOfPan = panGesture.locationInView(view)
|
|
|
|
|
- RightPanState.wasOpenAtStartOfPan = isRightOpen()
|
|
|
|
|
- RightPanState.wasHiddenAtStartOfPan = isRightHidden()
|
|
|
|
|
-
|
|
|
|
|
- rightViewController?.beginAppearanceTransition(RightPanState.wasHiddenAtStartOfPan, animated: true)
|
|
|
|
|
-
|
|
|
|
|
- addShadowToView(rightContainerView)
|
|
|
|
|
- setOpenWindowLevel()
|
|
|
|
|
- case UIGestureRecognizerState.Changed:
|
|
|
|
|
- if RightPanState.lastState != .Began && RightPanState.lastState != .Changed {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let translation: CGPoint = panGesture.translationInView(panGesture.view!)
|
|
|
|
|
- rightContainerView.frame = applyRightTranslation(translation, toFrame: RightPanState.frameAtStartOfPan)
|
|
|
|
|
- applyRightOpacity()
|
|
|
|
|
- applyRightContentViewScale()
|
|
|
|
|
-
|
|
|
|
|
- case UIGestureRecognizerState.Ended, UIGestureRecognizerState.Cancelled:
|
|
|
|
|
- if RightPanState.lastState != .Changed {
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let velocity: CGPoint = panGesture.velocityInView(panGesture.view)
|
|
|
|
|
- let panInfo: PanInfo = panRightResultInfoForVelocity(velocity)
|
|
|
|
|
-
|
|
|
|
|
- if panInfo.action == .Open {
|
|
|
|
|
- if !RightPanState.wasHiddenAtStartOfPan {
|
|
|
|
|
- rightViewController?.beginAppearanceTransition(true, animated: true)
|
|
|
|
|
- }
|
|
|
|
|
- openRightWithVelocity(panInfo.velocity)
|
|
|
|
|
-
|
|
|
|
|
- track(.RightFlickOpen)
|
|
|
|
|
- } else {
|
|
|
|
|
- if RightPanState.wasHiddenAtStartOfPan {
|
|
|
|
|
- rightViewController?.beginAppearanceTransition(false, animated: true)
|
|
|
|
|
- }
|
|
|
|
|
- closeRightWithVelocity(panInfo.velocity)
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
-
|
|
|
|
|
- track(.RightFlickClose)
|
|
|
|
|
- }
|
|
|
|
|
- case UIGestureRecognizerState.Failed, UIGestureRecognizerState.Possible:
|
|
|
|
|
- break
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- RightPanState.lastState = panGesture.state
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func openLeftWithVelocity(velocity: CGFloat) {
|
|
|
|
|
- let xOrigin: CGFloat = leftContainerView.frame.origin.x
|
|
|
|
|
- let finalXOrigin: CGFloat = 0.0
|
|
|
|
|
-
|
|
|
|
|
- var frame = leftContainerView.frame;
|
|
|
|
|
- frame.origin.x = finalXOrigin;
|
|
|
|
|
-
|
|
|
|
|
- var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
|
|
|
|
|
- if velocity != 0.0 {
|
|
|
|
|
- duration = Double(fabs(xOrigin - finalXOrigin) / velocity)
|
|
|
|
|
- duration = Double(fmax(0.1, fmin(1.0, duration)))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- addShadowToView(leftContainerView)
|
|
|
|
|
-
|
|
|
|
|
- UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.leftContainerView.frame = frame
|
|
|
|
|
- strongSelf.opacityView.layer.opacity = Float(SlideMenuOptions.contentViewOpacity)
|
|
|
|
|
-
|
|
|
|
|
- SlideMenuOptions.contentViewDrag == true ? (strongSelf.mainContainerView.transform = CGAffineTransformMakeTranslation(SlideMenuOptions.leftViewWidth, 0)) : (strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(SlideMenuOptions.contentViewScale, SlideMenuOptions.contentViewScale))
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- }) { [weak self](Bool) -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.disableContentInteraction()
|
|
|
|
|
- strongSelf.leftViewController?.endAppearanceTransition()
|
|
|
|
|
- strongSelf.delegate?.leftDidOpen?()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func openRightWithVelocity(velocity: CGFloat) {
|
|
|
|
|
- let xOrigin: CGFloat = rightContainerView.frame.origin.x
|
|
|
|
|
-
|
|
|
|
|
- // CGFloat finalXOrigin = SlideMenuOptions.rightViewOverlapWidth;
|
|
|
|
|
- let finalXOrigin: CGFloat = CGRectGetWidth(view.bounds) - rightContainerView.frame.size.width
|
|
|
|
|
-
|
|
|
|
|
- var frame = rightContainerView.frame
|
|
|
|
|
- frame.origin.x = finalXOrigin
|
|
|
|
|
-
|
|
|
|
|
- var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
|
|
|
|
|
- if velocity != 0.0 {
|
|
|
|
|
- duration = Double(fabs(xOrigin - CGRectGetWidth(view.bounds)) / velocity)
|
|
|
|
|
- duration = Double(fmax(0.1, fmin(1.0, duration)))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- addShadowToView(rightContainerView)
|
|
|
|
|
-
|
|
|
|
|
- UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.rightContainerView.frame = frame
|
|
|
|
|
- strongSelf.opacityView.layer.opacity = Float(SlideMenuOptions.contentViewOpacity)
|
|
|
|
|
-
|
|
|
|
|
- SlideMenuOptions.contentViewDrag == true ? (strongSelf.mainContainerView.transform = CGAffineTransformMakeTranslation(-SlideMenuOptions.rightViewWidth, 0)) : (strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(SlideMenuOptions.contentViewScale, SlideMenuOptions.contentViewScale))
|
|
|
|
|
- }
|
|
|
|
|
- }) { [weak self](Bool) -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.disableContentInteraction()
|
|
|
|
|
- strongSelf.rightViewController?.endAppearanceTransition()
|
|
|
|
|
- strongSelf.delegate?.rightDidOpen?()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func closeLeftWithVelocity(velocity: CGFloat) {
|
|
|
|
|
-
|
|
|
|
|
- let xOrigin: CGFloat = leftContainerView.frame.origin.x
|
|
|
|
|
- let finalXOrigin: CGFloat = leftMinOrigin()
|
|
|
|
|
-
|
|
|
|
|
- var frame: CGRect = leftContainerView.frame;
|
|
|
|
|
- frame.origin.x = finalXOrigin
|
|
|
|
|
-
|
|
|
|
|
- var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
|
|
|
|
|
- if velocity != 0.0 {
|
|
|
|
|
- duration = Double(fabs(xOrigin - finalXOrigin) / velocity)
|
|
|
|
|
- duration = Double(fmax(0.1, fmin(1.0, duration)))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.leftContainerView.frame = frame
|
|
|
|
|
- strongSelf.opacityView.layer.opacity = 0.0
|
|
|
|
|
- strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
|
|
|
|
|
- }
|
|
|
|
|
- }) { [weak self](Bool) -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.removeShadow(strongSelf.leftContainerView)
|
|
|
|
|
- strongSelf.enableContentInteraction()
|
|
|
|
|
- strongSelf.leftViewController?.endAppearanceTransition()
|
|
|
|
|
- strongSelf.delegate?.leftDidClose?()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public func closeRightWithVelocity(velocity: CGFloat) {
|
|
|
|
|
-
|
|
|
|
|
- let xOrigin: CGFloat = rightContainerView.frame.origin.x
|
|
|
|
|
- let finalXOrigin: CGFloat = CGRectGetWidth(view.bounds)
|
|
|
|
|
-
|
|
|
|
|
- var frame: CGRect = rightContainerView.frame
|
|
|
|
|
- frame.origin.x = finalXOrigin
|
|
|
|
|
-
|
|
|
|
|
- var duration: NSTimeInterval = Double(SlideMenuOptions.animationDuration)
|
|
|
|
|
- if velocity != 0.0 {
|
|
|
|
|
- duration = Double(fabs(xOrigin - CGRectGetWidth(view.bounds)) / velocity)
|
|
|
|
|
- duration = Double(fmax(0.1, fmin(1.0, duration)))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { [weak self]() -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.rightContainerView.frame = frame
|
|
|
|
|
- strongSelf.opacityView.layer.opacity = 0.0
|
|
|
|
|
- strongSelf.mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
|
|
|
|
|
- }
|
|
|
|
|
- }) { [weak self](Bool) -> Void in
|
|
|
|
|
- if let strongSelf = self {
|
|
|
|
|
- strongSelf.removeShadow(strongSelf.rightContainerView)
|
|
|
|
|
- strongSelf.enableContentInteraction()
|
|
|
|
|
- strongSelf.rightViewController?.endAppearanceTransition()
|
|
|
|
|
- strongSelf.delegate?.rightDidClose?()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- public override func toggleLeft() {
|
|
|
|
|
- if isLeftOpen() {
|
|
|
|
|
- closeLeft()
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- // Tracking of close tap is put in here. Because closeMenu is due to be call even when the menu tap.
|
|
|
|
|
-
|
|
|
|
|
- track(.LeftTapClose)
|
|
|
|
|
- } else {
|
|
|
|
|
- openLeft()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func isLeftOpen() -> Bool {
|
|
|
|
|
- return leftViewController != nil && leftContainerView.frame.origin.x == 0.0
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func isLeftHidden() -> Bool {
|
|
|
|
|
- return leftContainerView.frame.origin.x <= leftMinOrigin()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public override func toggleRight() {
|
|
|
|
|
- if isRightOpen() {
|
|
|
|
|
- closeRight()
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
-
|
|
|
|
|
- // Tracking of close tap is put in here. Because closeMenu is due to be call even when the menu tap.
|
|
|
|
|
- track(.RightTapClose)
|
|
|
|
|
- } else {
|
|
|
|
|
- openRight()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func isRightOpen() -> Bool {
|
|
|
|
|
- return rightViewController != nil && rightContainerView.frame.origin.x == CGRectGetWidth(view.bounds) - rightContainerView.frame.size.width
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func isRightHidden() -> Bool {
|
|
|
|
|
- return rightContainerView.frame.origin.x >= CGRectGetWidth(view.bounds)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func changeMainViewController(mainViewController: UIViewController, close: Bool) {
|
|
|
|
|
-
|
|
|
|
|
- removeViewController(self.mainViewController)
|
|
|
|
|
- self.mainViewController = mainViewController
|
|
|
|
|
- setUpViewController(mainContainerView, targetViewController: mainViewController)
|
|
|
|
|
- if (close) {
|
|
|
|
|
- closeLeft()
|
|
|
|
|
- closeRight()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func changeLeftViewWidth(width: CGFloat) {
|
|
|
|
|
-
|
|
|
|
|
- SlideMenuOptions.leftViewWidth = width;
|
|
|
|
|
- var leftFrame: CGRect = view.bounds
|
|
|
|
|
- leftFrame.size.width = width
|
|
|
|
|
- leftFrame.origin.x = leftMinOrigin();
|
|
|
|
|
- let leftOffset: CGFloat = 0
|
|
|
|
|
- leftFrame.origin.y = leftFrame.origin.y + leftOffset
|
|
|
|
|
- leftFrame.size.height = leftFrame.size.height - leftOffset
|
|
|
|
|
- leftContainerView.frame = leftFrame;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func changeRightViewWidth(width: CGFloat) {
|
|
|
|
|
-
|
|
|
|
|
- SlideMenuOptions.rightBezelWidth = width;
|
|
|
|
|
- var rightFrame: CGRect = view.bounds
|
|
|
|
|
- rightFrame.size.width = width
|
|
|
|
|
- rightFrame.origin.x = rightMinOrigin()
|
|
|
|
|
- let rightOffset: CGFloat = 0
|
|
|
|
|
- rightFrame.origin.y = rightFrame.origin.y + rightOffset;
|
|
|
|
|
- rightFrame.size.height = rightFrame.size.height - rightOffset
|
|
|
|
|
- rightContainerView.frame = rightFrame;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func changeLeftViewController(leftViewController: UIViewController, closeLeft:Bool) {
|
|
|
|
|
-
|
|
|
|
|
- removeViewController(self.leftViewController)
|
|
|
|
|
- self.leftViewController = leftViewController
|
|
|
|
|
- setUpViewController(leftContainerView, targetViewController: leftViewController)
|
|
|
|
|
- if closeLeft {
|
|
|
|
|
- self.closeLeft()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func changeRightViewController(rightViewController: UIViewController, closeRight:Bool) {
|
|
|
|
|
- removeViewController(self.rightViewController)
|
|
|
|
|
- self.rightViewController = rightViewController;
|
|
|
|
|
- setUpViewController(rightContainerView, targetViewController: rightViewController)
|
|
|
|
|
- if closeRight {
|
|
|
|
|
- self.closeRight()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func leftMinOrigin() -> CGFloat {
|
|
|
|
|
- return -SlideMenuOptions.leftViewWidth
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func rightMinOrigin() -> CGFloat {
|
|
|
|
|
- return CGRectGetWidth(view.bounds)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private func panLeftResultInfoForVelocity(velocity: CGPoint) -> PanInfo {
|
|
|
|
|
-
|
|
|
|
|
- let thresholdVelocity: CGFloat = 1000.0
|
|
|
|
|
- let pointOfNoReturn: CGFloat = CGFloat(floor(leftMinOrigin())) + SlideMenuOptions.pointOfNoReturnWidth
|
|
|
|
|
- let leftOrigin: CGFloat = leftContainerView.frame.origin.x
|
|
|
|
|
-
|
|
|
|
|
- var panInfo: PanInfo = PanInfo(action: .Close, shouldBounce: false, velocity: 0.0)
|
|
|
|
|
-
|
|
|
|
|
- panInfo.action = leftOrigin <= pointOfNoReturn ? .Close : .Open;
|
|
|
|
|
-
|
|
|
|
|
- if velocity.x >= thresholdVelocity {
|
|
|
|
|
- panInfo.action = .Open
|
|
|
|
|
- panInfo.velocity = velocity.x
|
|
|
|
|
- } else if velocity.x <= (-1.0 * thresholdVelocity) {
|
|
|
|
|
- panInfo.action = .Close
|
|
|
|
|
- panInfo.velocity = velocity.x
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return panInfo
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func panRightResultInfoForVelocity(velocity: CGPoint) -> PanInfo {
|
|
|
|
|
-
|
|
|
|
|
- let thresholdVelocity: CGFloat = -1000.0
|
|
|
|
|
- let pointOfNoReturn: CGFloat = CGFloat(floor(CGRectGetWidth(view.bounds)) - SlideMenuOptions.pointOfNoReturnWidth)
|
|
|
|
|
- let rightOrigin: CGFloat = rightContainerView.frame.origin.x
|
|
|
|
|
-
|
|
|
|
|
- var panInfo: PanInfo = PanInfo(action: .Close, shouldBounce: false, velocity: 0.0)
|
|
|
|
|
-
|
|
|
|
|
- panInfo.action = rightOrigin >= pointOfNoReturn ? .Close : .Open
|
|
|
|
|
-
|
|
|
|
|
- if velocity.x <= thresholdVelocity {
|
|
|
|
|
- panInfo.action = .Open
|
|
|
|
|
- panInfo.velocity = velocity.x
|
|
|
|
|
- } else if (velocity.x >= (-1.0 * thresholdVelocity)) {
|
|
|
|
|
- panInfo.action = .Close
|
|
|
|
|
- panInfo.velocity = velocity.x
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return panInfo
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func applyLeftTranslation(translation: CGPoint, toFrame:CGRect) -> CGRect {
|
|
|
|
|
-
|
|
|
|
|
- var newOrigin: CGFloat = toFrame.origin.x
|
|
|
|
|
- newOrigin += translation.x
|
|
|
|
|
-
|
|
|
|
|
- let minOrigin: CGFloat = leftMinOrigin()
|
|
|
|
|
- let maxOrigin: CGFloat = 0.0
|
|
|
|
|
- var newFrame: CGRect = toFrame
|
|
|
|
|
-
|
|
|
|
|
- if newOrigin < minOrigin {
|
|
|
|
|
- newOrigin = minOrigin
|
|
|
|
|
- } else if newOrigin > maxOrigin {
|
|
|
|
|
- newOrigin = maxOrigin
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- newFrame.origin.x = newOrigin
|
|
|
|
|
- return newFrame
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func applyRightTranslation(translation: CGPoint, toFrame: CGRect) -> CGRect {
|
|
|
|
|
-
|
|
|
|
|
- var newOrigin: CGFloat = toFrame.origin.x
|
|
|
|
|
- newOrigin += translation.x
|
|
|
|
|
-
|
|
|
|
|
- let minOrigin: CGFloat = rightMinOrigin()
|
|
|
|
|
- let maxOrigin: CGFloat = rightMinOrigin() - rightContainerView.frame.size.width
|
|
|
|
|
- var newFrame: CGRect = toFrame
|
|
|
|
|
-
|
|
|
|
|
- if newOrigin > minOrigin {
|
|
|
|
|
- newOrigin = minOrigin
|
|
|
|
|
- } else if newOrigin < maxOrigin {
|
|
|
|
|
- newOrigin = maxOrigin
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- newFrame.origin.x = newOrigin
|
|
|
|
|
- return newFrame
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func getOpenedLeftRatio() -> CGFloat {
|
|
|
|
|
-
|
|
|
|
|
- let width: CGFloat = leftContainerView.frame.size.width
|
|
|
|
|
- let currentPosition: CGFloat = leftContainerView.frame.origin.x - leftMinOrigin()
|
|
|
|
|
- return currentPosition / width
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func getOpenedRightRatio() -> CGFloat {
|
|
|
|
|
-
|
|
|
|
|
- let width: CGFloat = rightContainerView.frame.size.width
|
|
|
|
|
- let currentPosition: CGFloat = rightContainerView.frame.origin.x
|
|
|
|
|
- return -(currentPosition - CGRectGetWidth(view.bounds)) / width
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func applyLeftOpacity() {
|
|
|
|
|
-
|
|
|
|
|
- let openedLeftRatio: CGFloat = getOpenedLeftRatio()
|
|
|
|
|
- let opacity: CGFloat = SlideMenuOptions.contentViewOpacity * openedLeftRatio
|
|
|
|
|
- opacityView.layer.opacity = Float(opacity)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private func applyRightOpacity() {
|
|
|
|
|
- let openedRightRatio: CGFloat = getOpenedRightRatio()
|
|
|
|
|
- let opacity: CGFloat = SlideMenuOptions.contentViewOpacity * openedRightRatio
|
|
|
|
|
- opacityView.layer.opacity = Float(opacity)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func applyLeftContentViewScale() {
|
|
|
|
|
- let openedLeftRatio: CGFloat = getOpenedLeftRatio()
|
|
|
|
|
- let scale: CGFloat = 1.0 - ((1.0 - SlideMenuOptions.contentViewScale) * openedLeftRatio);
|
|
|
|
|
- let drag: CGFloat = SlideMenuOptions.leftViewWidth + leftContainerView.frame.origin.x
|
|
|
|
|
-
|
|
|
|
|
- SlideMenuOptions.contentViewDrag == true ? (mainContainerView.transform = CGAffineTransformMakeTranslation(drag, 0)) : (mainContainerView.transform = CGAffineTransformMakeScale(scale, scale))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func applyRightContentViewScale() {
|
|
|
|
|
- let openedRightRatio: CGFloat = getOpenedRightRatio()
|
|
|
|
|
- let scale: CGFloat = 1.0 - ((1.0 - SlideMenuOptions.contentViewScale) * openedRightRatio)
|
|
|
|
|
- let drag: CGFloat = rightContainerView.frame.origin.x - mainContainerView.frame.size.width
|
|
|
|
|
-
|
|
|
|
|
- SlideMenuOptions.contentViewDrag == true ? (mainContainerView.transform = CGAffineTransformMakeTranslation(drag, 0)) : (mainContainerView.transform = CGAffineTransformMakeScale(scale, scale))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func addShadowToView(targetContainerView: UIView) {
|
|
|
|
|
- targetContainerView.layer.masksToBounds = false
|
|
|
|
|
- targetContainerView.layer.shadowOffset = SlideMenuOptions.shadowOffset
|
|
|
|
|
- targetContainerView.layer.shadowOpacity = Float(SlideMenuOptions.shadowOpacity)
|
|
|
|
|
- targetContainerView.layer.shadowRadius = SlideMenuOptions.shadowRadius
|
|
|
|
|
- targetContainerView.layer.shadowPath = UIBezierPath(rect: targetContainerView.bounds).CGPath
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func removeShadow(targetContainerView: UIView) {
|
|
|
|
|
- targetContainerView.layer.masksToBounds = true
|
|
|
|
|
- mainContainerView.layer.opacity = 1.0
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func removeContentOpacity() {
|
|
|
|
|
- opacityView.layer.opacity = 0.0
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private func addContentOpacity() {
|
|
|
|
|
- opacityView.layer.opacity = Float(SlideMenuOptions.contentViewOpacity)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func disableContentInteraction() {
|
|
|
|
|
- mainContainerView.userInteractionEnabled = false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func enableContentInteraction() {
|
|
|
|
|
- mainContainerView.userInteractionEnabled = true
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func setOpenWindowLevel() {
|
|
|
|
|
- if (SlideMenuOptions.hideStatusBar) {
|
|
|
|
|
- dispatch_async(dispatch_get_main_queue(), {
|
|
|
|
|
- if let window = UIApplication.sharedApplication().keyWindow {
|
|
|
|
|
- window.windowLevel = UIWindowLevelStatusBar + 1
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func setCloseWindowLevel() {
|
|
|
|
|
- if (SlideMenuOptions.hideStatusBar) {
|
|
|
|
|
- dispatch_async(dispatch_get_main_queue(), {
|
|
|
|
|
- if let window = UIApplication.sharedApplication().keyWindow {
|
|
|
|
|
- window.windowLevel = UIWindowLevelNormal
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func setUpViewController(targetView: UIView, targetViewController: UIViewController?) {
|
|
|
|
|
- if let viewController = targetViewController {
|
|
|
|
|
- addChildViewController(viewController)
|
|
|
|
|
- viewController.view.frame = targetView.bounds
|
|
|
|
|
- targetView.addSubview(viewController.view)
|
|
|
|
|
- viewController.didMoveToParentViewController(self)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private func removeViewController(viewController: UIViewController?) {
|
|
|
|
|
- if let _viewController = viewController {
|
|
|
|
|
- _viewController.view.layer.removeAllAnimations()
|
|
|
|
|
- _viewController.willMoveToParentViewController(nil)
|
|
|
|
|
- _viewController.view.removeFromSuperview()
|
|
|
|
|
- _viewController.removeFromParentViewController()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func closeLeftNonAnimation(){
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- let finalXOrigin: CGFloat = leftMinOrigin()
|
|
|
|
|
- var frame: CGRect = leftContainerView.frame;
|
|
|
|
|
- frame.origin.x = finalXOrigin
|
|
|
|
|
- leftContainerView.frame = frame
|
|
|
|
|
- opacityView.layer.opacity = 0.0
|
|
|
|
|
- mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
|
|
|
|
|
- removeShadow(leftContainerView)
|
|
|
|
|
- enableContentInteraction()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func closeRightNonAnimation(){
|
|
|
|
|
- setCloseWindowLevel()
|
|
|
|
|
- let finalXOrigin: CGFloat = CGRectGetWidth(view.bounds)
|
|
|
|
|
- var frame: CGRect = rightContainerView.frame
|
|
|
|
|
- frame.origin.x = finalXOrigin
|
|
|
|
|
- rightContainerView.frame = frame
|
|
|
|
|
- opacityView.layer.opacity = 0.0
|
|
|
|
|
- mainContainerView.transform = CGAffineTransformMakeScale(1.0, 1.0)
|
|
|
|
|
- removeShadow(rightContainerView)
|
|
|
|
|
- enableContentInteraction()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // MARK: UIGestureRecognizerDelegate
|
|
|
|
|
- public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
|
|
|
|
|
-
|
|
|
|
|
- let point: CGPoint = touch.locationInView(view)
|
|
|
|
|
-
|
|
|
|
|
- if gestureRecognizer == leftPanGesture {
|
|
|
|
|
- return slideLeftForGestureRecognizer(gestureRecognizer, point: point)
|
|
|
|
|
- } else if gestureRecognizer == rightPanGesture {
|
|
|
|
|
- return slideRightViewForGestureRecognizer(gestureRecognizer, withTouchPoint: point)
|
|
|
|
|
- } else if gestureRecognizer == leftTapGesture {
|
|
|
|
|
- return isLeftOpen() && !isPointContainedWithinLeftRect(point)
|
|
|
|
|
- } else if gestureRecognizer == rightTapGesture {
|
|
|
|
|
- return isRightOpen() && !isPointContainedWithinRightRect(point)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // returning true here helps if the main view is fullwidth with a scrollview
|
|
|
|
|
- public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
|
|
|
- return SlideMenuOptions.simultaneousGestureRecognizers
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func slideLeftForGestureRecognizer( gesture: UIGestureRecognizer, point:CGPoint) -> Bool{
|
|
|
|
|
- return isLeftOpen() || SlideMenuOptions.panFromBezel && isLeftPointContainedWithinBezelRect(point)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func isLeftPointContainedWithinBezelRect(point: CGPoint) -> Bool{
|
|
|
|
|
- if let bezelWidth = SlideMenuOptions.leftBezelWidth {
|
|
|
|
|
- var leftBezelRect: CGRect = CGRectZero
|
|
|
|
|
- var tempRect: CGRect = CGRectZero
|
|
|
|
|
-
|
|
|
|
|
- CGRectDivide(view.bounds, &leftBezelRect, &tempRect, bezelWidth, CGRectEdge.MinXEdge)
|
|
|
|
|
- return CGRectContainsPoint(leftBezelRect, point)
|
|
|
|
|
- } else {
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func isPointContainedWithinLeftRect(point: CGPoint) -> Bool {
|
|
|
|
|
- return CGRectContainsPoint(leftContainerView.frame, point)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- private func slideRightViewForGestureRecognizer(gesture: UIGestureRecognizer, withTouchPoint point: CGPoint) -> Bool {
|
|
|
|
|
- return isRightOpen() || SlideMenuOptions.rightPanFromBezel && isRightPointContainedWithinBezelRect(point)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func isRightPointContainedWithinBezelRect(point: CGPoint) -> Bool {
|
|
|
|
|
- if let rightBezelWidth = SlideMenuOptions.rightBezelWidth {
|
|
|
|
|
- var rightBezelRect: CGRect = CGRectZero
|
|
|
|
|
- var tempRect: CGRect = CGRectZero
|
|
|
|
|
- let bezelWidth: CGFloat = CGRectGetWidth(view.bounds) - rightBezelWidth
|
|
|
|
|
-
|
|
|
|
|
- CGRectDivide(view.bounds, &tempRect, &rightBezelRect, bezelWidth, CGRectEdge.MinXEdge)
|
|
|
|
|
-
|
|
|
|
|
- return CGRectContainsPoint(rightBezelRect, point)
|
|
|
|
|
- } else {
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private func isPointContainedWithinRightRect(point: CGPoint) -> Bool {
|
|
|
|
|
- return CGRectContainsPoint(rightContainerView.frame, point)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-extension UIViewController {
|
|
|
|
|
-
|
|
|
|
|
- public func slideMenuController() -> SlideMenuController? {
|
|
|
|
|
- var viewController: UIViewController? = self
|
|
|
|
|
- while viewController != nil {
|
|
|
|
|
- if viewController is SlideMenuController {
|
|
|
|
|
- return viewController as? SlideMenuController
|
|
|
|
|
- }
|
|
|
|
|
- viewController = viewController?.parentViewController
|
|
|
|
|
- }
|
|
|
|
|
- return nil;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func addLeftBarButtonWithImage(buttonImage: UIImage) {
|
|
|
|
|
- let leftButton: UIBarButtonItem = UIBarButtonItem(image: buttonImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(self.toggleLeft))
|
|
|
|
|
- navigationItem.leftBarButtonItem = leftButton;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func addRightBarButtonWithImage(buttonImage: UIImage) {
|
|
|
|
|
- let rightButton: UIBarButtonItem = UIBarButtonItem(image: buttonImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(self.toggleRight))
|
|
|
|
|
- navigationItem.rightBarButtonItem = rightButton;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func toggleLeft() {
|
|
|
|
|
- slideMenuController()?.toggleLeft()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func toggleRight() {
|
|
|
|
|
- slideMenuController()?.toggleRight()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func openLeft() {
|
|
|
|
|
- slideMenuController()?.openLeft()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func openRight() {
|
|
|
|
|
- slideMenuController()?.openRight() }
|
|
|
|
|
-
|
|
|
|
|
- public func closeLeft() {
|
|
|
|
|
- slideMenuController()?.closeLeft()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public func closeRight() {
|
|
|
|
|
- slideMenuController()?.closeRight()
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Please specify if you want menu gesuture give priority to than targetScrollView
|
|
|
|
|
- public func addPriorityToMenuGesuture(targetScrollView: UIScrollView) {
|
|
|
|
|
- guard let slideController = slideMenuController(), let recognizers = slideController.view.gestureRecognizers else {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- for recognizer in recognizers where recognizer is UIPanGestureRecognizer {
|
|
|
|
|
- targetScrollView.panGestureRecognizer.requireGestureRecognizerToFail(recognizer)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|