Combine UIPageViewController with iOS 7 UINavigationController back-swipe gesture

I have a navigation controller that pushes a view controller (PARENT) that contains a UIPageViewController (PAGES). Now I used pan / swipe gestures to switch between the children of the page view controller. However, I can no longer call the PARENT-view controller using swipe gestures from the left border of the screen, because it is interpreted as a gesture in PAGES.

Is it possible to make this transition on the screen when the leftmost controller is shown?

Two ideas:

  • Returns zero in pageViewController:viewControllerBeforeViewController not working.

  • Limit the touch area described here.

Or is there an easier way?

+6
ios objective-c ios7
Apr 24 '14 at 11:43
source share
5 answers

I had the same situation as @smallwisdom, but was handled differently.

I have a view controller A that I push on top of my navigation controller stack. This view controller A contains a horizontal scroll view that extends all the way from the left side of the screen to the right.

In this case, when I wanted to scroll the screen to the view controller A from the navigation controller stack, all I did was scroll this horizontal scroll view.

The solution is pretty simple.

Inside my view controller A , I have the code:

 _contentScrollView = [[UIScrollView alloc] init]; [self.view addSubview:_contentScrollView]; for (UIGestureRecognizer *gestureRecognizer in _contentScrollView.gestureRecognizers) { [gestureRecognizer requireGestureRecognizerToFail:self.navigationController.interactivePopGestureRecognizer]; } 

It works great. What does it mean? It tells scrollView gesture recognizers that they need to wait to see if any other gesture recognizer recognizes the current gesture.

If this other one does not recognize, then they will no longer have to wait, and they may try to recognize the current gesture.

If this other recognizer is successful and recognizes the current gesture, all pending gesture recognizers will automatically fail.

This other gesture recognizer that they should wait for is installed as the interactivePopGestureRecognizer navigation controller. He is responsible for napkin to back gestures.

+11
May 22 '14 at 16:20
source share

I basically agree with @ancajic's answer. I would like to provide an additional case where you set the UIPageViewController transitionStyle parameter to “Scroll” in which you cannot set gesureRecognizers, a workaround:

 if (self.navigationController?.interactivePopGestureRecognizer != nil) { for view in self.pageViewController!.view.subviews { if let scrollView = view as? UIScrollView { scrollView.panGestureRecognizer.requireGestureRecognizerToFail(self.navigationController!.interactivePopGestureRecognizer!); } } } 
+5
Oct 19 '15 at 2:48
source share

I had a similar problem in one of my projects and I used the following method. In my case, it was one of those left-hand menus that were really popular before iOS 7.

My solution was to set UINavigationControllerDelegate, and then implemented the following:

 - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { // enable the interactive menu gesture only if at root, otherwise enable the pop gesture BOOL isRoot = (navigationController.viewControllers.firstObject == viewController); self.panGestureRecognizer.enabled = isRoot; navigationController.interactivePopGestureRecognizer.enabled = !self.panGestureRecognizer.enabled; } 

EDIT:

In addition, you need a hook in the UIPageViewController gesture recognizer. (They are not returned by the gestureRecognizers property for the scroll style view controller.) This is annoying, but the only way I found access to this is to thin out the scrollview gesture recognizers and look for a panorama gesture. Then set the pointer for it and enable / disable based on whether the left-most view controller is currently displayed.

If you want the right swipe to be on, replace the panorama gesture with your own gesture recognizer in the form of a subclass that can be conditionally recognized depending on the direction of the panorama gestures.

+1
Apr 24 '14 at 11:23
source share

First find the UIPageViewController scrollView

 extension UIPageViewController { var bk_scrollView: UIScrollView? { if let v = view as? UIScrollView { return v } // view.subviews 只有一个元素,其类型是 _UIQueuingScrollView,是 UIScrollView 的子类// view.subviews have only one item of which the type is _UIQueuingScrollView, which is kind of UIScrollView subclass. for v in view.subviews where v is UIScrollView { return v as? UIScrollView } return nil } } 

Second, install the gestureRecognizer dependency.

 override func viewDidLoad() { super.viewDidLoad() if let ges = navigationController?.interactivePopGestureRecognizer { pageViewController.bk_scrollView?.panGestureRecognizer.require(toFail: ges) } } 
0
Nov 16 '17 at 2:55
source share

Fast version of @Lcsky's answer:

 if let interactivePopGesture = self.navigationController?.interactivePopGestureRecognizer, let pageViewController = self.swipeVC?.pageViewController { let subView = pageViewController.view.subviews for view in subView { if let scrollView = view as? UIScrollView{ scrollView.panGestureRecognizer.require(toFail: interactivePopGesture) } } } 
0
Feb 28
source share



All Articles