How can I implement “drag right to dismiss” a View Controller that's in a navigation stack?

后端 未结 6 1860
忘了有多久
忘了有多久 2020-12-07 18:24

By default, if you drag right from the left edge of the screen, it will drag away the ViewController and take it off the stack.

I want to extend this functionality t

6条回答
  •  旧时难觅i
    2020-12-07 18:30

    Swipe Right to dismiss the View Controller

    Swift 5 Version - (Also removed the gesture recognition when swiping from right - to - left)

    Important - In ‘Attributes inspector’ of VC2, set the ‘Presentation’ value from ‘Full Screen’ to ‘Over Full Screen’. This will allow VC1 to be visible during dismissing VC2 via gesture — without it, there will be black screen behind VC2 instead of VC1.

    class ViewController: UIGestureRecognizerDelegate, UINavigationControllerDelegate {
    
        var initialTouchPoint: CGPoint = CGPoint(x: 0, y: 0)
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            navigationController?.interactivePopGestureRecognizer?.delegate = self
            let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
            view.addGestureRecognizer(panGesture)
        }
    
        @objc func handlePanGesture(_ sender: UIPanGestureRecognizer) {
            let touchPoint = sender.location(in: self.view?.window)
            let percent = max(sender.translation(in: view).x, 0) / view.frame.width
            let velocity = sender.velocity(in: view).x
    
            if sender.state == UIGestureRecognizer.State.began {
                initialTouchPoint = touchPoint
            } else if sender.state == UIGestureRecognizer.State.changed {
                if touchPoint.x - initialTouchPoint.x > 0 {
                    self.view.frame = CGRect(x: touchPoint.x - initialTouchPoint.x, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
                }
            } else if sender.state == UIGestureRecognizer.State.ended || sender.state == UIGestureRecognizer.State.cancelled {
    
                if percent > 0.5 || velocity > 1000 {
                    navigationController?.popViewController(animated: true)
                } else {
                    UIView.animate(withDuration: 0.3, animations: {
                        self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
                    })
                }
            }
        }
    }
    

    Hope this helps. Feel free to suggest changes if necessary.

提交回复
热议问题