swift版左右侧滑菜单

可以只传入左菜单参数,也可以只传入右菜单参数,也可以同时传入左右菜单,都支持。

AppDelegate 里 didFinishLaunchingWithOptions 方法中实现

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        window = UIWindow(frame: UIScreen.main.bounds)
        //创建根视图控制器
        print(UserDefaults.standard.bool(forKey: FirstLaunch))
        //检测用户是不是第一次启动
        if !UserDefaults.standard.bool(forKey: FirstLaunch) {
            //是第一次启动
            self.window?.rootViewController = FirstIntroduceVC()
            UserDefaults.standard.set(true, forKey: FirstLaunch)
        }else{
            let slider = HZSSliderController(centerViewController: TabBarVC(), leftViewController: AttentionVC(), rightViewController: nil)
            slider.sideMovable = true
            slider.scaleEnable = true
            self.window?.backgroundColor = UIColor.white
            self.window?.rootViewController = slider
        }
        window?.makeKeyAndVisible()
        // Override point for customization after application launch.
        return true
    }

其中有营养的就是下面代码

let slider = HZSSliderController(centerViewController: TabBarVC(), leftViewController: AttentionVC(), rightViewController: nil)
            slider.sideMovable = truehttp://www.jianshu.com/p/72e778cfbbe3
            slider.scaleEnable = true
            self.window?.backgroundColor = UIColor.white
            self.window?.rootViewController = slider

默认效果

04173925_iJhj.gif

sideMenu.gif

sideMovable = true

04173926_3NN8.gif

sideMenu1.gif

scaleEnable = true

04173927_uebd.gif

sideMenu2.gif

sideMovable = true && scaleEnable = true

04173927_5yBC.gif

sideMenu3.gif

 

自定义HZSSliderController 代码如下

//
//  HZSSliderController.swift
//  TodayNews
//
//  Created by Simon on 2017/1/4.
//  Copyright © 2017年 Simon. All rights reserved.
//

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: TimeInterval = 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 = CGPoint(x: 0, y: 0)
    private var centerCenter: CGPoint = CGPoint(x: 0, y: 0)
    private var rightCenter: CGPoint = CGPoint(x: 0, y: 0)
    private var distanceFromLeft: CGFloat = 0
    private var centerButton: UIButton?
    private var enable_edge: CGFloat = 75
    private var screen_width: CGFloat {
        return UIScreen.main.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: Bool) -> Void {
        guard let left = leftVC else { return }
        
        view.window?.endEditing(true)
        left.view.isHidden = false
        rightVC?.view.isHidden = true
        let center = view.center
        UIView.animate(withDuration: 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 = CGAffineTransform(scaleX: self.scale, y: 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: Bool) -> Void {
        guard let right = rightVC else { return }
        
        view.window?.endEditing(true)
        leftVC?.view.isHidden = true
        right.view.isHidden = false
        let center = view.center
        UIView.animate(withDuration: 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 = CGAffineTransform(scaleX: self.scale, y: 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: Bool) -> Void {
        view.window?.endEditing(true)
        let center = view.center
        UIView.animate(withDuration: 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 = CGAffineTransform.identity
        }) { (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: viewController)
        hideViewController(viewController: centerVC)
        centerVC = viewController
        UIView.animate(withDuration: 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(viewController: left)
            left.view.center = CGPoint(x: self.view.center.x - menu_begin, y: self.view.center.y)
        }
        if let right = rightVC {
            self.addViewController(viewController: right)
            right.view.center = CGPoint(x: self.view.center.x + menu_begin, y: self.view.center.y)
        }
        self.addViewController(viewController: centerVC)
        
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panHandler (_:)))
        panGesture.delegate = self
        view.addGestureRecognizer(panGesture)
    }
    
    func panHandler(_ gesture: UIPanGestureRecognizer) {
        guard leftVC != nil || rightVC != nil else { return }
        
        let xTranslation = gesture.translation(in: view).x
        distanceFromLeft += xTranslation
        gesture.setTranslation(CGPoint(x: 0, y: 0), in: view)
        
        switch gesture.state {
        case .began:
            let startXPoint = gesture.location(in: 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 = CGAffineTransform(scaleX: localScale, y: localScale)
            }
        case .ended:
            let velocity = gesture.velocity(in: 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.isHidden = false
        rightVC?.view.isHidden = 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.isHidden = false
        leftVC?.view.isHidden = 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.clear
            centerButton?.addTarget(self, action: #selector(hzs_sliderController?.centerButtonAction), for: .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.didMove(toParentViewController: self)
    }
    
    private func hideViewController(viewController: UIViewController) {
        viewController.willMove(toParentViewController: nil)
        viewController.view.removeFromSuperview()
        viewController.removeFromParentViewController()
    }
    
    //MARK: UIGestureRecognizerDelegate
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive 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.location(in: 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.parent
        while iter != nil {
            if iter is HZSSliderController {
                return iter as? HZSSliderController
            } else if iter?.parent != nil && iter?.parent != iter {
                iter = iter?.parent
            } else {
                iter = nil
            }
        }
        return nil
    }
    
    func hzs_sliderControllerShowLeftViewController(animated: Bool) {
        self.hzs_sliderController?.showLeftViewController(animated: animated)
    }
    
    func hzs_sliderControllerShowRightViewController(animated: Bool) {
        self.hzs_sliderController?.showRightViewController(animated: animated)
    }
    
    func hzs_sliderControllerShowCenterViewController(animated: Bool) {
        self.hzs_sliderController?.showCenterViewController(animated: animated)
    }
    
    func hzs_sliderControllerSetCenterRecoverColsure(closure: @escaping () -> Void) {
        self.hzs_sliderController?.recoverCenterClosure = closure
    }
}

文/我黑_太阳难道是你家的_(简书作者)
原文链接:http://www.jianshu.com/p/72e778cfbbe3
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

转载于:https://my.oschina.net/u/2818284/blog/818696

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值