左右侧滑菜单swift

作者: 乌黑的太阳 | 来源:发表于2016-06-03 22:44 被阅读1377次
    可以只传入左菜单参数,也可以只传入右菜单参数,也可以同时传入左右菜单,都支持。(先有oc版,再写的swift版)
    HZSSliderController(centerViewController: UIViewController, leftViewController: UIViewController?, rightViewController: UIViewController?)
    

    默认效果

    sideMenu.gif

    sideMovable = true

    sideMenu1.gif

    scaleEnable = true

    sideMenu2.gif

    sideMovable = true && scaleEnable = true

    sideMenu3.gif
    import UIKit
    
    class HZSSliderController: UIViewController, UIGestureRecognizerDelegate {
        
        enum HZSSliderState {
            case Cener, Left, Right
        }
        
        //Public property
        private(set) var leftVC: UIViewController?
        private(set) var centerVC: UIViewController
        private(set) var rightVC: UIViewController?
        private(set) var state: HZSSliderState = .Cener
        var animationDuration: NSTimeInterval = 0.25
        var scaleEnable: Bool = false
        var scale: CGFloat = 0.85
        var sideMovable: Bool = false
        var recoverCenterClosure: (() -> Void)?
        var backgroundIMG: UIImage? {
            didSet {
                backgroundImgView.image = backgroundIMG
            }
        }
        //Private property
        private let backgroundImgView: UIImageView = UIImageView()
        private var touchAtLeft: Bool = false
        private var leftCenter: CGPoint = CGPointZero
        private var centerCenter: CGPoint = CGPointZero
        private var rightCenter: CGPoint = CGPointZero
        private var distanceFromLeft: CGFloat = 0
        private var centerButton: UIButton?
        private var enable_edge: CGFloat = 75
        private var screen_width: CGFloat {
            return UIScreen.mainScreen().bounds.size.width
        }
        private var mini_triggerDistance: CGFloat {
            return screen_width*0.2
        }
        private var max_moveDistance: CGFloat {
            return scaleEnable ? (screen_width - 90) : (screen_width - 70)
        }
        private var menu_begin: CGFloat {
            return sideMovable ? 60 : 0
        }
        
        //Public func
        init(centerViewController: UIViewController, leftViewController: UIViewController?, rightViewController: UIViewController?) {
            self.centerVC = centerViewController
            self.leftVC = leftViewController
            self.rightVC = rightViewController
            super.init(nibName: nil, bundle: nil)
        }
        
        func showLeftViewController(animated animated: Bool) -> Void {
            guard let left = leftVC else { return }
            
            view.window?.endEditing(true)
            left.view.hidden = false
            rightVC?.view.hidden = true
            let center = view.center
            UIView.animateWithDuration(animated ? animationDuration : 0, animations: { 
                left.view.center = center
                self.centerVC.view.center = CGPoint(x: center.x + self.max_moveDistance, y: center.y)
                if self.scaleEnable {
                    self.centerVC.view.transform = CGAffineTransformMakeScale(self.scale, self.scale)
                }
                }) { (finished) in
                    self.state = .Left
                    self.rightVC?.view.center = CGPoint(x: center.x + self.menu_begin, y: center.y)
                    self.addCenterButton()
                    self.distanceFromLeft = self.max_moveDistance
            }
        }
        
        func showRightViewController(animated animated: Bool) -> Void {
            guard let right = rightVC else { return }
            
            view.window?.endEditing(true)
            leftVC?.view.hidden = true
            right.view.hidden = false
            let center = view.center
            UIView.animateWithDuration(animated ? animationDuration : 0, animations: { 
                right.view.center = center
                self.centerVC.view.center = CGPoint(x: center.x - self.max_moveDistance, y: center.y)
                if self.scaleEnable {
                    self.centerVC.view.transform = CGAffineTransformMakeScale(self.scale, self.scale)
                }
                }) { (finished) in
                    self.state = .Right
                    self.leftVC?.view.center = CGPoint(x: center.x - self.menu_begin, y: center.y)
                    self.addCenterButton()
                    self.distanceFromLeft = -self.max_moveDistance
            }
        }
        
        func showCenterViewController(animated animated: Bool) -> Void {
            view.window?.endEditing(true)
            let center = view.center
            UIView.animateWithDuration(animated ? animationDuration : 0, animations: { 
                self.leftVC?.view.center = CGPoint(x: center.x - self.menu_begin, y: center.y)
                self.rightVC?.view.center = CGPoint(x: center.x + self.menu_begin, y: center.y)
                self.centerVC.view.center = center
                self.centerVC.view.transform = CGAffineTransformIdentity
                }) { (finished) in
                    self.state = .Cener
                    self.centerButton?.removeFromSuperview()
                    self.centerButton = nil
                    self.distanceFromLeft = 0
            }
        }
        
        func setCenterViewControllerWith(viewController: UIViewController, animated: Bool) -> Void {
            if centerVC == viewController { return }
            
            viewController.view.center = centerVC.view.center
            viewController.view.transform = centerVC.view.transform
            viewController.view.alpha = 0;
            addViewController(viewController)
            hideViewController(centerVC)
            centerVC = viewController
            UIView.animateWithDuration(animated ? animationDuration : 0, animations: { 
                viewController.view.alpha = 1.0
                }, completion: nil)
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //backgroundIMG
            backgroundImgView.frame = view.bounds
            backgroundImgView.contentMode = .ScaleAspectFill
            backgroundImgView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
            view.addSubview(backgroundImgView)
            
            //childView
            if let left = leftVC {
                self.addViewController(left)
                left.view.center = CGPoint(x: self.view.center.x - menu_begin, y: self.view.center.y)
            }
            if let right = rightVC {
                self.addViewController(right)
                right.view.center = CGPoint(x: self.view.center.x + menu_begin, y: self.view.center.y)
            }
            self.addViewController(centerVC)
            
            //panGesture
            let panGesture = UIPanGestureRecognizer(target: self, action: #selector(HZSSliderController.panHandler(_:)))
            panGesture.delegate = self
            view.addGestureRecognizer(panGesture)
        }
        
        func panHandler(gesture: UIPanGestureRecognizer) {
            guard leftVC != nil || rightVC != nil else { return }
            
            let xTranslation = gesture.translationInView(view).x
            distanceFromLeft += xTranslation
            gesture.setTranslation(CGPointZero, inView: view)
            
            switch gesture.state {
            case .Began:
                let startXPoint = gesture.locationInView(view).x
                if startXPoint <= enable_edge {
                    touchAtLeft = true
                } else {
                    touchAtLeft = false
                }
                view.window?.endEditing(true)
            case .Changed:
                if let left = leftVC {
                    leftCenter = left.view.center
                }
                if let right = rightVC {
                    rightCenter = right.view.center
                }
                centerCenter = centerVC.view.center
                
                switch state {
                case .Cener:
                    if touchAtLeft && leftVC != nil {
                        movingAroundLeft()
                    } else if touchAtLeft == false && rightVC != nil {
                        movingAroundRight()
                    }
                case .Left:
                    movingAroundLeft()
                case .Right:
                    movingAroundRight()
                }
                if let left = leftVC {
                    left.view.center = leftCenter
                }
                if let right = rightVC {
                    right.view.center = rightCenter
                }
                centerVC.view.center = centerCenter
                
                //中间视图的缩放
                if scaleEnable && ((rightVC != nil && touchAtLeft == false) || (leftVC != nil && touchAtLeft == true)) {
                    let localScale = (1 - abs(distanceFromLeft)/max_moveDistance) * (1 - scale) + scale
                    centerVC.view.transform = CGAffineTransformMakeScale(localScale, localScale)
                }
            case .Ended:
                let velocity = gesture.velocityInView(view)
                switch state {
                case .Cener:
                    if distanceFromLeft > mini_triggerDistance && velocity.x > 0{
                        showLeftViewController(animated: true)
                    } else if distanceFromLeft < -mini_triggerDistance && velocity.x < 0 {
                        showRightViewController(animated: true)
                    } else {
                        showCenterViewController(animated: true)
                    }
                case .Left:
                    if distanceFromLeft < max_moveDistance - mini_triggerDistance && velocity.x < 0 {
                        showCenterViewController(animated: true)
                    } else {
                        showLeftViewController(animated: true)
                    }
                case .Right:
                    if distanceFromLeft > -max_moveDistance + mini_triggerDistance && velocity.x > 0 {
                        showCenterViewController(animated: true)
                    } else {
                        showRightViewController(animated: true)
                    }
                }
            default:
                return
            }
        }
        
        //MARK: Private method
        private func movingAroundLeft() {
            guard let left = leftVC else { return }
            
            left.view.hidden = false
            rightVC?.view.hidden = true
            if distanceFromLeft >= max_moveDistance {
                leftCenter = view.center
                centerCenter.x = view.center.x + max_moveDistance
                distanceFromLeft = max_moveDistance
            } else if distanceFromLeft <= 0 {
                leftCenter.x = -menu_begin
                centerCenter = view.center
                distanceFromLeft = 0
            } else {
                leftCenter.x = view.center.x - menu_begin + abs(distanceFromLeft/max_moveDistance) * menu_begin
                centerCenter.x = view.center.x + distanceFromLeft
            }
        }
        
        private func movingAroundRight() {
            guard let right = rightVC else { return }
            
            right.view.hidden = false
            leftVC?.view.hidden = true
            if distanceFromLeft <= -max_moveDistance {
                rightCenter.x = view.center.x
                centerCenter.x = view.center.x - max_moveDistance
                distanceFromLeft = -max_moveDistance
            } else if distanceFromLeft >= 0 {
                rightCenter.x = view.center.x + menu_begin
                centerCenter = view.center
                distanceFromLeft = 0
            } else {
                rightCenter.x = view.center.x + menu_begin + abs(distanceFromLeft/max_moveDistance) * -menu_begin
                centerCenter.x = view.center.x + distanceFromLeft
            }
        }
        
        private func addCenterButton() {
            if centerButton == nil {
                centerButton = UIButton(type: .System)
                centerButton?.backgroundColor = UIColor.clearColor()
                centerButton?.addTarget(self, action: #selector(HZSSliderController.centerButtonAction), forControlEvents: .TouchUpInside)
                view.addSubview(centerButton!)
            }
            centerButton?.frame = centerVC.view.frame
        }
    func centerButtonAction() {
            showCenterViewController(animated: true)
            if let closure = recoverCenterClosure {
                closure()
            }
        }
        
        //MARK: viewController operate
        private func addViewController(viewController: UIViewController) {
            viewController.view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
            self.addChildViewController(viewController)
            self.view.addSubview(viewController.view)
            viewController.didMoveToParentViewController(self)
        }
        
        private func hideViewController(viewController: UIViewController) {
            viewController.willMoveToParentViewController(nil)
            viewController.view.removeFromSuperview()
            viewController.removeFromParentViewController()
        }
        
        //MARK: UIGestureRecognizerDelegate
        func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
            if centerVC is UINavigationController {
                let nav = centerVC as! UINavigationController
                if nav.viewControllers.count > 1 { return false }
            }
            
            if gestureRecognizer is UIPanGestureRecognizer {
                let point = touch.locationInView(gestureRecognizer.view)
                if state == .Left {
                    if point.x >= screen_width - enable_edge {
                        return true
                    } else {
                        return false
                    }
                } else if state == .Right {
                    if point.x <= enable_edge {
                        return true
                    } else {
                        return false
                    }
                } else {
                    if point.x >= enable_edge && point.x <= screen_width - enable_edge {
                        return false
                    } else {
                        return true
                    }
                }
            }
            return true
        }
    }
    
    extension UIViewController {
        var hzs_sliderController: HZSSliderController? {
            var iter = self.parentViewController
            while iter != nil {
                if iter is HZSSliderController {
                    return iter as? HZSSliderController
                } else if iter?.parentViewController != nil && iter?.parentViewController != iter {
                    iter = iter?.parentViewController
                } else {
                    iter = nil
                }
            }
            return nil
        }
        
        func hzs_sliderControllerShowLeftViewController(animated animated: Bool) {
            self.hzs_sliderController?.showLeftViewController(animated: animated)
        }
        
        func hzs_sliderControllerShowRightViewController(animated animated: Bool) {
            self.hzs_sliderController?.showRightViewController(animated: animated)
        }
        
        func hzs_sliderControllerShowCenterViewController(animated animated: Bool) {
            self.hzs_sliderController?.showCenterViewController(animated: animated)
        }
        
        func hzs_sliderControllerSetCenterRecoverColsure(closure: () -> Void) {
            self.hzs_sliderController?.recoverCenterClosure = closure
        }
    }
    

    相关文章

      网友评论

        本文标题:左右侧滑菜单swift

        本文链接:https://www.haomeiwen.com/subject/mlrldttx.html