将UIPageViewController滑动与iOS 7 UINavigationController反滑动手势相结合

时间:2014-04-24 11:43:17

标签: ios objective-c ios7

我有一个导航控制器,用于推送包含UIPageViewController( PAGES )的视图控制器( PARENT )。现在我使用平移/滑动手势在页面视图控制器的子节点之间切换。但是,我无法再使用屏幕左边框中的滑动手势弹出 PARENT - 视图控制器,因为它被解释为 PAGES 中的手势。

当显示最左侧的视图控制器时,是否可以完成刷卡操作?

两个想法:

  1. pageViewController:viewControllerBeforeViewController - >中返回nil不起作用。

  2. 将触摸区域限制为described here

  3. 或者有更简单的方法吗?

5 个答案:

答案 0 :(得分:15)

我和@smallwisdom的情况相同,但处理方式不同。

我有一个视图控制器A,我可以将其推到导航控制器的堆栈之上。 此视图控制器A包含一个水平滚动视图,从屏幕左侧一直延伸到右侧。

在这种情况下,当我想从导航控制器的堆栈中滑动屏幕以弹出视图控制器A时,我最终做的就是滚动此水平滚动视图。

解决方案非常简单。

在我的视图控制器A中,我有这样的代码:

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

效果很好。这是做什么的? 它告诉scrollView的手势识别器,他们必须等待一些其他手势识别器是否能识别当前手势。

如果其他无法识别,则他们将不再需要等待,他们可以尝试识别当前的手势。

如果其他识别器成功并识别当前手势,则所有等待的手势识别器将自动失败。

他们必须等待的其他手势识别器被设置为导航控制器的interactivePopGestureRecognizer。他负责滑动到后退的姿势。

答案 1 :(得分:5)

我大多同意@ ancajic的回答。当你将UIPageViewController的transitionStyle设置为Scroll'时,我想提供一个额外的案例,你不会在其中设置gestureRecognizers,解决方法是:

if (self.navigationController?.interactivePopGestureRecognizer != nil)
{
    for view in self.pageViewController!.view.subviews
    {
        if let scrollView = view as? UIScrollView
        {
            scrollView.panGestureRecognizer.requireGestureRecognizerToFail(self.navigationController!.interactivePopGestureRecognizer!);
        }
    }
}

答案 2 :(得分:1)

我的一个项目中有类似的问题,并使用以下方法。就我而言,它是iOS 7之前真正流行的左侧菜单之一。

我的解决方案是设置UINavigationControllerDelegate,然后实现以下内容:

- (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;
}

编辑:

此外,您需要一个挂钩到UIPageViewController的手势识别器。 (对于滚动视图样式页面视图控制器,gestureRecognizers属性不会返回它们。)这很烦人,但我发现访问它的唯一方法是遍历滚动视图&#39 ; s手势识别器并寻找平移手势。然后设置指向它的指针,并根据您当前是否显示最左侧的视图控制器来启用/禁用。

如果您想要保持正确的滑动,请将平移手势替换为您自己的子扫描平移手势识别器,可以根据平移手势的方向有条件地识别。

答案 3 :(得分:0)

首先,找到UIPageViewController' s 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's subclass.
        for v in view.subviews where v is UIScrollView {
            return v as? UIScrollView 
        }
        return nil
    }
}

其次,设置gestureRecognizer的依赖性。

override func viewDidLoad() {
    super.viewDidLoad()
    if let ges = navigationController?.interactivePopGestureRecognizer {
        pageViewController.bk_scrollView?.panGestureRecognizer.require(toFail: ges)
    }
}

答案 4 :(得分:0)

@Lcsky的答案的快速版本:

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)
        }
    }    
}