在单独的 child 视图控制器中的 UITableView 之上的 UICollectionView

UICollectionView on top of a UITableView in separate child view controllers

我的视图层次结构如下。

ParentContainerVC    
..UINavigationViewController (child of ParentContainerVC)
....UITableViewController (child of navigation view controller)
..UICollectionViewController (child of ParentContainerVC)

托管 UICollectionView 的 VC 正确拦截了滚动事件,但下面的 UITableView 仍处于冻结状态。两者的大小都适合屏幕的整个宽度/高度,但应该允许独立滚动(如果您想知道,UICollectionView 不会遮挡下面的 UITableView - 但用户需要能够在同时)。

在托管集合视图的VC中,我实现了:

extension UICollectionViewController: UIGestureRecognizerDelegate {
  public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
  }
}

然而这并没有帮助。我认为这是因为视图控制器已添加为 child 控制器,这在同级视图控制器中不起作用。

ParentContainerVC 只是一个容器视图控制器,带有两个children。我需要做什么才能让触摸/滚动事件独立地在两个 children / siblings 上工作?

这有点棘手,但我最终想通了。问题本质上是,一旦一个视图(深度优先)通过了命中测试,命中测试视图后面或周围的其他视图就会停止接收触摸。

诀窍是在所有其他内容前面添加另一个虚拟 UIView 以编排和合并所有触摸。然后从每个 UIScrollView / UICollectionView / UITableView 子视图控制器中获取 .panGestureRecognizer,并将它们添加到这个虚拟视图控制器中。

现在,所有可滚动列表,无论视图层次结构中的哪个位置,都开始滚动并响应触摸,无需摆弄 hitTest 或子类化。

要进一步细化哪个滚动视图首先对触摸做出反应,您可以添加另一个 UIPanGestureRecognizer 然后执行类似 .require(toFail: myNewPanGesture) 的操作以及您希望此手势如何以及何时执行的实现失败。这样您就可以控制要先滚动的可滚动内容。