微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在两个UIPageControllers之间连续滚动

如何解决在两个UIPageControllers之间连续滚动

在以下情况下,我试图实现连续滚动:

MainViewController(UIViewController)包含一个UIPageViewControllertransitionStyle: .scroll)的实例,该实例仅管理两个控制器。 ItemsViewController(UIViewController)和ProfileViewController(UIViewController)。 MainViewController允许在主控制器和配置文件控制器之间水平滚动。

现在,ProfileViewController包含UIPageViewControllertransitionStyle: .scroll)的另一个实例,可以在两个UIViewController(A和B)之间水平滚动。

问题是,当我滚动到ProfileViewController并开始在A和B之间滚动时,我无法滚动(向右)返回到ItemsViewController。似乎ProfileViewController的UIPageViewController正在拦截滚动手势,并且没有将它们传递给MainViewController的UIPageViewController实例,您将陷入ProfileViewController中。

这是一些代码

final class MainViewController: UIViewController {
    private let pageController: UIPageViewController
    let itemsController: ItemsViewController
    let profileController: ProfileViewController
    private var controllers = [UIViewController]()
    private(set) var currentPageIndex = 0

    override init(...) {
        itemsController = ItemsViewController(...)
        controllers.append(itemsController)
        profileController = ProfileViewController(...)
        controllers.append(profileController)
        pageController = UIPageViewController(transitionStyle: .scroll,navigationorientation: .horizontal,options: nil)
        super.init(...)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        configurePageController()
    }

    func configurePageController() {
        pageController.dataSource = self
        pageController.delegate = self
        pageController.setViewControllers([itemsController],direction: .forward,animated: false)

        for view in pageController.view.subviews {
            if let scrollView = view as? UIScrollView {
                scrollView.delegate = self
                break
            }
        }
    }
} 

extension MainViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController,viewControllerBefore viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController) {
            if index > 0 {
                return controllers[index - 1]
            }
            else {
                return nil
            }
        }
        return nil
    }

    func pageViewController(_ pageViewController: UIPageViewController,viewControllerAfter viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController) {
            if index < controllers.count - 1 {
                return controllers[index + 1]
            }
            else {
                return nil
            }
        }
        return nil
    }
}

extension MainViewController: UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController,didFinishAnimating finished: Bool,prevIoUsViewControllers: [UIViewController],transitionCompleted completed: Bool) {
        guard completed else {
            return
        }
        if let vc = pageController.viewControllers?.first,let index = controllers.firstIndex(of: vc) {
            currentPageIndex = index
        }
    }
}

// Freeze scrolling on the left and right edges 
extension MainViewController: uiscrollviewdelegate {
    private func freezScrolling(_ scrollView: UIScrollView) {
        if currentPageIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width,y: 0)
        }
        else if currentPageIndex == controllers.count - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width,y: 0)
        }
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        freezScrolling(scrollView)
    }

    func scrollViewWillEndDragging(_ scrollView: UIScrollView,withVeLocity veLocity: CGPoint,targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        freezScrolling(scrollView)
    }
}
final class ProfileViewController: UIViewController {
    private let pageController: UIPageViewController
    private lazy var controllers: [UIViewController] = [ControllerA,ControllerB]
    private var currentPageIndex = 0

    override init(...) {
        pageController = UIPageViewController(transitionStyle: .scroll,options: nil)
        super.init(...)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        configurePageController()
    }

    func configurePageController() {
        pageController.dataSource = self
        pageController.delegate = self

        for view in pageController.view.subviews {
            if let scrollView = view as? UIScrollView {
                scrollView.delegate = self
                break
            }
        }
    }

extension ProfileViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController,viewControllerBefore viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController),index > 0 {
            return controllers[index - 1]
        }
        return nil
    }

    func pageViewController(_ pageViewController: UIPageViewController,viewControllerAfter viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController),index < controllers.count - 1 {
            return controllers[index + 1]
        }
        return nil
    }
}

extension ProfileViewController: UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController,transitionCompleted completed: Bool) {
        guard completed else {
            return
        }

        if let vc = pageController.viewControllers?.first,let index = controllers.firstIndex(of: vc) {
            currentPageIndex = index
        }
    }
}

extension ProfileViewController: uiscrollviewdelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        freezScrolling(scrollView)
    }

    private func freezScrolling(_ scrollView: UIScrollView) {
        if currentPageIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width,y: 0)
        }
    }

    func scrollViewWillEndDragging(_ scrollView: UIScrollView,targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        freezScrolling(scrollView)
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。