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
}
P.s. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With