Recently, I encountered such a problem in the development. There was a UICollectionView that used horizontal sliding mode. When sliding to the right, it often conflicted with the gesture of swiping back, which resulted in the original intention to slide to the left, but the result was directly Pop to the previous page.
The experiment of a
The first thing that came to mind was to use the general method of gesture conflict, as follows:
if letgesture = self.navigationController? .interactivePopGestureRecognizer { gesture.require(toFail: self.collectionView.panGestureRecognizer) }Copy the code
It turns out that the effect of this method is equivalent to disabling the swipe back gesture, because the horizontal UIScrollView panGestureRecognizer will not fail, and one might immediately think of bounces, Add the self. CollectionView. Bounces = false try this effect, the results prove that this method still doesn’t work.
Experiment 2
If the simple method above fails, it is necessary to start from the interception of gesture events, which can be tried from the panGesture of UIScollView or the swiping gesture direction. Personally, I prefer the swiping gesture direction, so I will record the experiment process in this direction.
Set the proxy in WXViewController as follows:
self.navigationController? .interactivePopGestureRecognizer?.delegate = selfif letgesture = self.navigationController? .interactivePopGestureRecognizer { self.collectionView.panGestureRecognizer.require(toFail: gesture) }Copy the code
Implement the UIGestureDelegate protocol
extension WXViewController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if self.collectionView.contentOffset.x <= 0 {
return true
}
return false}}Copy the code
The experiment proved that the above method worked, but with a side effect, the sideslip gestures on other pages were disabled, apparently because the sideslip gestures were intercepted by the WXViewController, and the sideslip gestures on other pages had a nil delegate, causing the system to fail to respond. The solution is to save interactivePopGestureRecognizer? Delegate’s proxy, and then restore it where appropriate, add the following code to the code above:
popGestrueDelegate = self.navigationController? .interactivePopGestureRecognizer?.delegate self.navigationController?.interactivePopGestureRecognizer?.delegate = self . override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.navigationController? .interactivePopGestureRecognizer?.delegate = popGestrueDelegate }Copy the code
The results showed that the above method solved the sideshow and horizontal sliding gesture conflict problem, but look at the code does not feel perfect, if other pages need to solve the gesture conflict, then need to copy the code, so continue to experiment.
Test three
Since interactivePopGestureRecognizer is defined in the UINavigationController, that we can also customize a UINavigationController, then intercept this gesture, and the code is as follows
/ * custom intercept gestures agreement * / protocol WXInteractiveGestureDelegate: NSObjectProtocol { func wxGestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool } /*WXNavigationController*/ override funcviewDidLoad() {
super.viewDidLoad()
self.interactivePopGestureRecognizer?.delegate = self
}
extension WXNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let topController = self.topViewController as? WXInteractiveGestureDelegate {
return topController.wxGestureRecognizerShouldBegin(gestureRecognizer)
}
return true}}Copy the code
And then implement that protocol in UIViewController that needs to intercept sideslip gestures,
extension WXViewController: WXInteractiveGestureDelegate {
func wxGestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if self.collectionView.contentOffset.x <= 0 {
return true
}
return false}}Copy the code
The interrupt point debugging found that the proxy method was called and returned true, but finally accepted the gesture was the panGestrue of UIScrollView, so we still need to add the following logic
if letgesture = self.navigationController? .interactivePopGestureRecognizer { self.collectionView.panGestureRecognizer.require(toFail: gesture) }Copy the code
Look at the effect after adding it. Well, it looks good.
Afterword.
As mentioned at the beginning, you can also start with the gesture of UIScrollView. If you are interested, you can try it. If there are other better methods, please leave comments and discuss.
If need to reprint, please inform the author and indicate the author and source, thank you!
Note:
1, GIF production tool, PicGIF