如何仅针对横向禁用UIPageViewController的分页?

时间:2019-01-10 16:40:37

标签: ios swift uipageviewcontroller uiinterfaceorientation device-orientation

我有一个 scroll 过渡样式UIPageViewController,仅当设备处于横向时才需要禁用分页。但是应该以纵向启用分页。

我在SO中遇到了类似的问题,但没有遇到我的特定需求。其中一些是:

How do I Disable the swipe gesture of UIPageViewController?

Disable Page scrolling in UIPageViewController

Disable/enable scrolling in UIPageViewController

Restrict UIPageViewController (with TransitionStyleScroll) pan gesture to a certain area

以上所有内容都表示完全禁止或限制平移手势到特定区域。

现在,如果我采取完全禁用的方法:

  • 我需要跟踪设备方向更改
  • 将方向设置为横向时禁用
  • 将方向更改为纵向时再次启用

如果我采取限制在某个区域的方法:

  • 我将需要找到某些区域

  • 需要计算某些区域(如前所述) 纵向和横向方向都不同

  • 某些用于纵向放置的区域必须是 UIPageViewController的整个范围

  • 用于横向的某些区域必须是非常小的区域 (其框架可能是0011),用户将无法 执行平移操作。这个帧的计算需要非常 精确,因为我的UIPageViewController占据了 主屏幕以横向显示。

  • 然后可能再次需要跟踪设备方向的变化 某些区域

  • 的计算

作者建议一些技术:

pvc.dataSource = nil // prevents paging

pvc.dataSource = `a valid dataSource object` // enables paging

因此,请手动启用+再次禁用。跟踪方向更改以及启用/禁用。

这对于我的特定用例而言并不安全,因为可能会多次分配数据源。


我认为还有其他方法无法修改以适应用例。

是否有实现我需要的捷径?

1 个答案:

答案 0 :(得分:0)

回答了我自己的问题,因为我已经达到了我所需要的。

子类化UIPageViewController是最简单的方法。我们必须找到页面视图控制器用来处理其平移手势相关工作的基础UIScrollView。我们将另一个UIPanGestureRecognizer添加到该内部滚动视图。该平移手势识别器本质上不会执行任何操作,但会阻止内部平移手势识别器仅针对横向识别。

示例实现:

class CustomPageViewController: UIPageViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        if let underlyingScrollView = view.subviews.compactMap({ $0 as? UIScrollView })
                                    .first {

            let pangestureRecognizer = UIPanGestureRecognizer()
            pangestureRecognizer.delegate = self
            underlyingScrollView.addGestureRecognizer(pangestureRecognizer)
            // at this point, the underlying scroll view will have two pan gesture
            // recognizer side by side. We have the control of our added pan gesture
            // recognizer through the delegate. We can conditionally recognize it or not
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
         shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) 
         -> Bool {
        // Returning true from here means, page view controller will behave as it is
        // Returning false means, paging will be blocked
        // As I needed to block paging only for landscape orientation, I'm just returning
        // if orientation is in portrait or not
        return UIApplication.shared.statusBarOrientation.isPortrait
    }

}