汉堡包菜单 UIPanGestureRecogniser

Hamburger Menu UIPanGestureRecogniser

我正在尝试以编程方式为我的应用程序制作一个汉堡包菜单,并且不使用任何插件。我从基础开始,所以只是试图在用户向右滑动时让 2 个 UIView 一起工作。 2个视图是主视图和汉堡包菜单。

到目前为止,UIView 已加载到正确的位置,并且当用户向右滑动时,边栏会随之滑动。但是,当用户放手时,UIView 也会向上滑动到中心,UIView 会固定到屏幕顶部。见下图:

一旦在上面迷路了就拉不下来了。我仍然可以左右滑动,但中心仍然限制在屏幕顶部。

我查看了我的代码,看不出我做错了什么?

这是我的代码:

    class gestureSwipe: UIViewController, UIGestureRecognizerDelegate {

    let screenHeight = UIScreen.main.bounds.height
    let screenWidth = UIScreen.main.bounds.width

    var trayOriginalCenter: CGPoint!
    var sideBarSwipeLeftOffset: CGFloat!
    var siderBarSwipeRight: CGPoint!
    var sideBarSwipeLeft: CGPoint!

    let sideBarUIView: UIView! = {
        let sideBarUIView = UIView()
        sideBarUIView.backgroundColor = UIColor(red:1.0, green:0.0, blue:0.0, alpha:1.0)
        sideBarUIView.translatesAutoresizingMaskIntoConstraints = false
        sideBarUIView.isUserInteractionEnabled = true
        return sideBarUIView
    }()

    let mainView: UIView = {
        let mainView = UIView()
        mainView.backgroundColor = UIColor(red:0.0, green:1.0, blue:0.0, alpha:1.0)
        mainView.translatesAutoresizingMaskIntoConstraints = false
        mainView.isUserInteractionEnabled = true
        return mainView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        let settingsButton = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(HandleSettings))
        navigationItem.leftBarButtonItem = settingsButton
        view.backgroundColor = UIColor.white

        view.addSubview(mainView)
        view.addSubview(sideBarUIView)

        let SideBarPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
        let MainViewPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
        mainView.addGestureRecognizer(MainViewPanGestureRecognizer)
        sideBarUIView.addGestureRecognizer(SideBarPanGestureRecognizer)

        sideBarSwipeLeftOffset = 80
        siderBarSwipeRight = sideBarUIView.center
        sideBarSwipeLeft = CGPoint(x: sideBarUIView.center.x + sideBarSwipeLeftOffset, y: sideBarUIView.center.y)

        setupLayout()
    }


    @IBAction func didPan(sender: UIPanGestureRecognizer) {
        let velocity = sender.velocity(in: view)
        let translation = sender.translation(in: view)

        if sender.state == .began {
            trayOriginalCenter = sideBarUIView.center
        } else if sender.state == .changed {
            print("Gesture began")
            sideBarUIView.center = CGPoint(x: trayOriginalCenter.x + translation.x, y: trayOriginalCenter.y)
        } else if sender.state == .ended {
            print("Gesture ended")
            if velocity.x > 0 {
                UIView.animate(withDuration: 0.3) {
                    self.sideBarUIView.center = self.sideBarSwipeLeft
                }
            } else {
                UIView.animate(withDuration: 0.3) {
                    self.sideBarUIView.center = self.siderBarSwipeRight
                }
            }

        }
    }

    @IBAction func HandleSettings(sender : UIButton) {
        print ("Show settings")
    }

    private func setupLayout(){

        // CONSTRAINTS

        mainView.heightAnchor.constraint(equalToConstant: screenHeight).isActive = true
        mainView.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true

        sideBarUIView.heightAnchor.constraint(equalToConstant: screenHeight).isActive = true
        sideBarUIView.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true
        sideBarUIView.rightAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
    }

}

所以我想出了问题。在 sender.state == .ended 中,我使用的是 self.sideBarUIView.center = self.sideBarSwipeLeft查看屏幕中央。

编辑:

我决定从头开始制作汉堡菜单。从这个例子中吸取一些想法:https://github.com/iosapptemplates/drawer-menu-swift

然后我终于去添加了一些不错的细节,比如如果菜单滑动得不够多,它就会再次隐藏起来。

如果有人需要的话,这是我的最终代码。

class hamburgerMenu: UIViewController, UIGestureRecognizerDelegate {

    let screenHeight = UIScreen.main.bounds.height
    let screenWidth = UIScreen.main.bounds.width
    var sideBarOriginalCenter: CGPoint!

    var mainView: UIView! = {
        let mainView = UIView()
        mainView.backgroundColor = UIColor(red:0.0, green:1.0, blue:0.0, alpha:1.0)
        mainView.translatesAutoresizingMaskIntoConstraints = false
        return mainView
    }()
    var overlayView: UIView! = {
        let viewBlack = UIView()
        viewBlack.backgroundColor = UIColor(red:0.0, green:0.0, blue:0.0, alpha:1.0)
        viewBlack.translatesAutoresizingMaskIntoConstraints = false
        return viewBlack
    }()
    var sideBarUIView: UIView! = {
        let sideBarUIView = UIView()
        sideBarUIView.backgroundColor = UIColor(red:1.0, green:0.0, blue:0.0, alpha:1.0)
        sideBarUIView.translatesAutoresizingMaskIntoConstraints = false
        return sideBarUIView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        let settingsButton = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(HandleSettings))
        navigationItem.leftBarButtonItem = settingsButton
        view.backgroundColor = UIColor.white

        view.addSubview(mainView)
        view.addSubview(overlayView)
        view.addSubview(sideBarUIView)

        overlayView.alpha = 0

        let swipeLeftGesture = UIPanGestureRecognizer(target: self, action: #selector(didPan(sender:)))
        mainView.addGestureRecognizer(swipeLeftGesture)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapOverlay))
        mainView.addGestureRecognizer(tapGesture)

        setupLayout()

    }

    @IBAction func didPan(sender: UIPanGestureRecognizer) {
        let translation = sender.translation(in: view)

        if sender.state == .began {
            sideBarOriginalCenter = sideBarUIView.center
        } else if sender.state == .changed {
            sideBarUIView.center = CGPoint(x: sideBarOriginalCenter.x + translation.x, y: sideBarUIView.center.y)
        } else if sender.state == .ended {
            let negHalfScreenWidth = ((self.screenWidth/2) * -1) / 2 // This should make -187.5 on iphoneX

            if sideBarUIView.center.x > negHalfScreenWidth {
                UIView.animate(withDuration: 0.3) {

                    if self.sideBarUIView.center.x > negHalfScreenWidth {
                        let leftSideOfScreen = self.screenWidth - self.screenWidth
                        self.sideBarUIView.center = CGPoint(x: leftSideOfScreen ,y: self.sideBarUIView.center.y)
                    }
                }
            } else {
                UIView.animate(withDuration: 0.3) {
                    let leftSideOfScreen = (self.screenWidth / 2) * -1
                    self.sideBarUIView.center = CGPoint(x: leftSideOfScreen ,y: self.sideBarUIView.center.y)
                }
            }
        }
    }

    @IBAction fileprivate func didTapOverlay() {
        UIView.animate(withDuration: 0.3, animations: {
            let leftSideOfScreen = (self.screenWidth / 2) * -1
            self.sideBarUIView.center = CGPoint(x: leftSideOfScreen ,y: self.sideBarUIView.center.y)
        }) { (success) in
        }
    }

    @IBAction func HandleSettings(sender : UIButton) {
        if (sideBarUIView.center.x == 0) {
            UIView.animate(withDuration: 0.3, animations: {
                let leftSideOfScreen = (self.screenWidth / 2) * -1
                self.sideBarUIView.center = CGPoint(x: leftSideOfScreen ,y: self.sideBarUIView.center.y)
            })
        } else if (sideBarUIView.center.x < -0.1) {
            UIView.animate(withDuration: 0.3, animations: {
                let leftSideOfScreen = self.screenWidth - self.screenWidth
                self.sideBarUIView.center = CGPoint(x: leftSideOfScreen ,y: self.sideBarUIView.center.y)
            })
        }
    }

    private func setupLayout(){
        mainView.heightAnchor.constraint(equalToConstant: screenHeight).isActive = true
        mainView.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true

        sideBarUIView.rightAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
        sideBarUIView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        sideBarUIView.heightAnchor.constraint(equalToConstant: screenHeight).isActive = true
        sideBarUIView.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true

        overlayView.heightAnchor.constraint(equalToConstant: screenHeight).isActive = true
        overlayView.widthAnchor.constraint(equalToConstant: screenWidth).isActive = true
    }

}