文档章节

swift版左右侧滑菜单

MeSimon
 MeSimon
发布于 2017/01/04 17:37
字数 1224
阅读 380
收藏 0

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

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
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

本文转载自:http://www.jianshu.com/p/72e778cfbbe3

MeSimon
粉丝 0
博文 2
码字总数 0
作品 0
浦东
私信 提问
“高仿手机 QQ 侧滑菜单” 3.0,支持 Swift 2.0

“高仿手机 QQ 侧滑菜单”开源项目 3.0 发布,支持 Swift 2.0。 再造 “手机QQ” 侧滑菜单: 1. 实现侧滑效果 2. 高仿左视图 3. 实现左右视图联动 此开源项目迁移到 Swift 2.0,增加精细到行...

JohnLui
2015/09/13
3.9K
8
Android UI 特效大全

Android UI特效大全 总体传送门:http://git.oschina.net/bob4j/Android-UI 基本上项目中都有效果图可自行查看 , 并且有些项目中都有README.md 文件,使用前请先阅读以下。 1.弧形(圆形)菜单...

不正经啊不正经
2015/07/31
1K
0
iOS好项目收集

项目 简述 日期 SCTableViewCell 类似与QQ侧滑删除Cell的Demo 201501018 JHChainableAnimations 可读性好使用方便的动画库,语法类似与Masonry,使用链式编程 20150506 awesome-ios-chart iOS...

哪一种黑
2016/03/20
57
0
SwiftSideslipLikeQQ 1.0 发布,再造“手机QQ” 侧滑菜单开源软件

SwiftSideslipLikeQQ 1.0 发布,此开源项目使用 swift 语言,基本再造了手机QQ的侧滑菜单,使用 Auto Layout 构造了左侧菜单,并实现了和主视图的联动。...

JohnLui
2015/04/14
3.8K
5
高仿手机QQ侧滑菜单 2.0 发布,增加 TabBar

SwiftSideslipLikeQQ 2.0 发布,加入了呼声很高的 TabBar,和“手机QQ”相似度爆表。 此开源项目使用 swift 语言,基本再造了手机QQ的侧滑菜单,使用 Auto Layout 构造了左侧菜单,并实现了和...

JohnLui
2015/05/02
4K
6

没有更多内容

加载失败,请刷新页面

加载更多

规则引擎

解决问题 版本迭代速度更不上业务变化,但是若多个业务同时变化,除了为每个业务设计专属配置项也不利于操作。就想服务接口单纯化,将复杂多变的业务逻辑交给规则引擎,让用户在web端或cs端自...

无极之岚
32分钟前
4
0
OSChina 周三乱弹 —— 欢迎你来做产品经理

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :10多次劲歌金曲获奖,更多叱咤歌坛排名,黎明才应该是四大天王之首,只可惜拍的电影太少。单曲循环一个多月的歌,力荐 《无名份的...

小小编辑
今天
249
9
500行代码,教你用python写个微信飞机大战

这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手。 帮助蹲厕族、YP族、饭圈女孩在无聊之余可以有一样东西让他们振作起来!...

上海小胖
今天
10
0
关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
7
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部