简体   繁体   中英

Conflict between ScrollView pan gesture and panGestureRecognizer

I have a UIScrollView in a UIViewController , which is showed modally by a segue, and an additional UIPanGestureRecognizer do dismiss the view controller by pan. This gesture only works if

 scrollView.contentOffset.y == 0

The problem is, now two pan gestures conflict with each other, and I can't scroll the view any more.

To solve this I have tried to use gestureRecognizer(_: shouldRecognizeSimultaneouslyWith:) method, returning yes, and also, I've tried to add my custom pan gesture to UIScrollView pan gesture recognizer like this:

 scrollView.panGestureRecognizer.addTarget(self, action: #selector(handlePanGesture(_:)))

But these don't solve the problem If you know how to solve this issue, I would appreciate your help.

EDITED

Here is the code for my pan gesture that dismisses the view controller:

     @IBAction func handlePanGesture(_ sender: UIPanGestureRecognizer) {
    let percentThreshold: CGFloat = 0.3

    if scrollView.contentOffset.y == 0 {
        let translation = sender.translation(in: view)
        let verticalMovement = translation.y / view.bounds.height
        let downwardMovement = fmaxf(Float(verticalMovement), 0.0)
        let downwardMovementPercent = fminf(downwardMovement, 1.0)
        let progress = CGFloat(downwardMovementPercent)

        guard let interactor = interactor else {return}
        switch sender.state {
        case .began:
            interactor.hasStarted = true
            dismiss(animated: true, completion: nil)
        case .changed:
            interactor.shouldFinish = progress > percentThreshold
            interactor.update(progress)
        case .cancelled:
            interactor.hasStarted = false
            interactor.cancel()
        case .ended:
            interactor.hasStarted = false
            interactor.shouldFinish ? interactor.finish() : interactor.cancel()
        default:
            break
        }

    }
}

EDITED_2 Here is the code for Interactor :

class Interactor: UIPercentDrivenInteractiveTransition {
var hasStarted = false
var shouldFinish = false 

}

Ps I know that there is a bunch of similar questions but they don't work for me.

To allow scrolling when a UIPanGestureRecognizer is on a ScrollView you need to create a UIGestureRecognizerDelegate that returns true on gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)

If you don't do this, scrolling will not be possible on the ScrollView.

This is done like so:

let scrollViewPanGesture = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:)))
scrollViewPanGesture.delegate = self
scrollView.addGestureRecognizer(scrollViewPanGesture)

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

I'm not sure but you can try adding the ViewController as a UIPanGestureRecognizer delegate of the swipe to dismiss pan gesture and implementing gestureRecognizerShouldBegin(_:) ;

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    return scrollView.contentOffset.y == 0
}

So the gesture to dismiss will start only if the content offset is zero.

在滚动视图下添加一个子视图并向其添加平移手势,而不是将其添加到 self.view 中,这肯定会与滚动视图的冲突

You did the right way when implemented gestureRecognizer(_: shouldRecognizeSimultaneouslyWith:)
But you must set the gesture delegate to current View Controller first:

let panGesture = UIPanGestureRecognizer.init(target: self, action: #selector(handlePanGesture(_:)))
panGesture.delegate = self // <--THIS
scrollView.addGestureRecognizer(panGesture)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM