【问题标题】:Detecting ScrollOffset in ScrollView inside ViewController held within UIPageViewController?在 UIPageViewController 中的 ViewController 内的 ScrollView 中检测 ScrollOffset?
【发布时间】:2019-11-10 07:07:53
【问题描述】:

我有一个 UIPageViewController,它包含一个 ContentUIViewController 数组,其中包含滚动视图。

当滚动视图滚动时,我想在 UIPageViewController 的父级视图控制器中识别这一点(添加为子级)

实现这一目标的最佳途径是什么?目前我尝试将didScroll 委托给ContentUIViewController 的视图模型,然后将其输入UIPageViewController 的父级以调整我想要折叠的标题高度,但它不能很好地工作/非常hacky

有没有办法在不通过视图模型反馈的情况下将子 vc 中的委托输出读取到父 vc?由于 UIPageViewController 的数组性质而不是单个子 VC,这被证明是棘手的。

更新:

private func generateContentControllers() -> [UIViewController] {
    var viewControllers: [UIViewController] = []
        viewControllers.append(ScrollableContentViewController(contentViews: infoViews))
        viewControllers.append(reviewsVC)
        viewControllers.append(ScrollableContentViewController(contentViews: helpViews))
    }
    return viewControllers
}

通过提供

var scrollingViewControllers: [UIViewController] { get }

添加了

    if let firstViewController = self.viewModel.scrollingViewControllers.first {
        pagingController.setViewControllers([firstViewController], direction: .forward, animated: false)
    }

【问题讨论】:

  • 你可以为 pageViewController 设置一个闭包并在 didScroll 方法中调用它
  • 同时添加相关代码。
  • 这只会让如果回调到创建它的视图模型,而不是父 VC,那么在太多地方涉及的代码太多,无法在问题中提供所有内容
  • 添加了该方法作为答案。看看你是否能与之相关。

标签: ios swift uiscrollview uipageviewcontroller


【解决方案1】:

您可以通过以下方式进行操作。

1.ContentUIViewController 中创建一个handler,在scrollViewDidScroll(_:) 方法中为每个contentOffset 更改调用。

class ContentUIViewController: UIViewController, UIScrollViewDelegate {
    var handler: ((CGPoint)->())?

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        handler?(scrollView.contentOffset)
    }
}

2.ParentVC 中,创建UIPageViewController 的实例并将其作为child 添加到其中。我想你已经这样做了。

您接下来需要做的是创建ContentUIViewControllerarray,并为每个实例设置我们之前创建的handler

每次在特定的ContentUIViewController 中滚动scrollView 时,都会调用此handler。我们将在这里获得scrollViewcontentOffset。用获取到的contentOffset调用updateHeaderHeight(for:)调整header的高度。

class ViewModel {
    private func generateContentControllers() -> [ContentUIViewController] {
        var viewControllers: [ContentUIViewController] = []
        //add your code here....
        return viewControllers
    }

    lazy var scrollingViewControllers: [ContentUIViewController] = {
        return self.generateContentControllers()
    }()
}

class ParentVC: UIViewController {
    let viewModel = ViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.viewModel.scrollingViewControllers.forEach {
            $0.handler = {(offset) in
                self.updateHeaderHeight(for: offset)
            }
        }
    }

    func updateHeaderHeight(for offset: CGPoint) {
        //add the code to adjust header height here...
    }

    //add rest of the code for pageViewController here....
}

【讨论】:

  • 我最初确实尝试过这个设置,这里的问题是 ContentUIViewController 是在 ParentVC 的视图模型中创建的,而不是在 ParentVC 中创建的,所以它进一步抽象,回调不会在 ParentVC 范围内并且 View Model 没有 ParentVC 的可见性,特别是它只能在其协议中提供一个值
  • 也可以在 ViewModel 中设置处理程序。并请添加相关代码。
  • ive 更新了 OP 以显示创建、传递的 VM 属性以及它是如何添加到父 VC 中的,如您所见,如果您在 VM 中添加处理程序,它会解析回来但您无法获得如果在该范围内有效,则将该值放入 parentVC 中使用
  • 根据您的要求更新了代码。此外,您需要编写大量代码以使用委托或闭包将 contentOffset 传递回视图层次结构。没有别的办法。
  • 感谢我设法通过解决您的方法使其工作,关键是 forEach 并在父 VC 中添加回调,谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-07
相关资源
最近更新 更多