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

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

默认效果

sideMenu.gif

sideMovable = true

sideMenu1.gif

scaleEnable = true

sideMenu2.gif

sideMovable = true && scaleEnable = true

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

swift版左右侧滑菜单相关推荐

  1. Android简易音乐重构MVVM Java版-新增推荐菜单及侧边栏展示(十二)

    Android简易音乐重构MVVM Java版-新增推荐菜单及侧边栏展示(十二) 关于 效果图 添加侧边栏 添加推荐歌单 新增RecommendAdapter适配器 修改DiscoverFragmen ...

  2. iOS仿QQ侧滑菜单、登录按钮动画、仿斗鱼直播APP、城市选择器、自动布局等源码

    iOS精选源码 QQ侧滑菜单,右滑菜单,QQ展开菜单,QQ好友分组 image 登录按钮 image 3分钟快捷创建高性能轮播图 ScrollView嵌套ScrolloView(UITableView ...

  3. iOS仿QQ侧滑菜单、登录按钮动画、仿斗鱼直播APP、城市选择器、自动布局等源码...

    iOS精选源码 QQ侧滑菜单,右滑菜单,QQ展开菜单,QQ好友分组 登录按钮 3分钟快捷创建高性能轮播图 ScrollView嵌套ScrolloView(UITableView .UICollecti ...

  4. 手机QQ侧滑菜单_从源码上一步步解析效果的实现

    本文思想来自洪洋大哥,本来写的原创的,有些朋友看到标题后认为是照搬翔哥的例子,仔细看看,会有不同,不过其中的主要思想还是翔哥的,滑动方面的算法还真是有些区别的,看完了就知道不一样,而且我这人比较啰嗦, ...

  5. 仿QQ侧滑菜单(二)

    在(一)https://blog.csdn.net/qq_36551426/article/details/80427352中讲了一下DrawerLayout的简单概念,但是这并不足以让我们去做一个完 ...

  6. iOS开发swift版异步加载网络图片(带缓存和缺省图片)

    iOS开发之swift版异步加载网络图片 与SDWebImage异步加载网络图片的功能相似,只是代码比较简单,功能没有SD的完善与强大,支持缺省添加图片,支持本地缓存. 异步加载图片的核心代码如下: ...

  7. 使用CoreLocation进行定位(Swift版)

    使用CoreLocation进行定位(Swift版) 在应用开发中,很多情况需要我们获取到当前的位置和高度信息,方便搜索周边,查看周边相同应用等,一切与定位有关的都得使用CoreLocation库,而 ...

  8. Swift版iOS游戏框架Sprite Kit基础教程下册

    Swift版iOS游戏框架Sprite Kit基础教程下册 试读下载地址:http://pan.baidu.com/s/1qWBdV0C  介绍:本教程是国内唯一的Swift版的Spritekit教程 ...

  9. iOS游戏框架Sprite Kit基础教程——Swift版上册

    iOS游戏框架Sprite Kit基础教程--Swift版上册 试读下载地址:http://pan.baidu.com/s/1qWBdV0C  介绍:本教程是国内唯一的Swift版的Spritekit ...

最新文章

  1. component lists rendered with v-for should have explicit keys
  2. Basic Level 1008. 数组元素循环右移问题 (20)
  3. 一篇文章带你详解 TCP/IP 协议(上)
  4. JVM调优系列:(四)GC垃圾回收
  5. 香港印象:维多利亚港湾·张学友的手印
  6. python数组替换_Python:替换数组中的值
  7. 产品经验谈:产品经理需要熟知几种常用思维模型
  8. Wordpress中显示页面当前位置
  9. 小波变换原理_基于电压行波原理故障测距的相关问题
  10. python 面向对象编程、别人么样用_Python 中的面向对象没有意义
  11. PHP留言板之提交留言
  12. 20套数据可视化大屏模板,附源码下载
  13. 51nod-1534 棋子游戏
  14. 计算机电源模式怎么删,电脑的电源选项里只剩下了平衡模式怎么办?
  15. Bigemap GIS Office软件 报价单
  16. 签名验证反爬,反反爬第二篇博客,Python爬虫120例
  17. 项目人力资源管理之编制项目人力资源管理计划
  18. ZeroMQ XPub/XSub模式
  19. 策略战棋游戏开发计划
  20. 在知识经济时代,如何实现企业内部的知识共享

热门文章

  1. Pytorch实战_神经网络的压缩(Network Compression)
  2. to_string函数的用法
  3. “网络巨轮”BGP基本实验演示
  4. 四千GB电脑技术高清视频教程和23万套各类源码模板
  5. html和css结合方式
  6. 能贴在iPhone桌面上的跨平台便签工具
  7. jquery each循环遍历完再执行的方法
  8. Ubuntu18.04 和 windows 10双系统 错误: `/EFI/Microsoft/Boot/bootmgfw.efi‘ not found
  9. java protostuff 好处,java序列化Protostuff和Serializable的区别
  10. 踏上天路之旅 寻找心灵净化圣地