UICollectionView 消耗垂直平移手势

UICollectionView consuming vertical pan gesture

我有一个 UICollectionView,它位于 UITableView 和 UIScrollView 内。 collection 视图是一个水平滚动的项目轮播,如果 collection 视图中有足够多的项目,它就可以正常工作,因此它比屏幕的宽度还宽。但是我遇到的问题是,如果只有一两个项目(不足以填满屏幕的宽度),那么 collection 视图似乎会消耗垂直平移手势并且不会让滚动视图滚动。

这是我的应用程序当前的布局方式。有滚动视图(下图中的绿色),它包含页面上的所有内容。在里面,有一个 table 视图,它有多个部分。每个部分都有一个可点击的部分 header。点击 header 部分后,该部分会通过添加包含 collection 视图的一行来扩展。 collection 视图是水平滚动流布局 collection 视图。

只要 collection 视图中有足够的 collection 视图单元格,它就会从屏幕上消失(如上图所示。但是如果只有一个项目,例如(如下图所示),那么如果在 collection 视图内的任意位置(下图中蓝色区域或棕褐色区域的任意位置)开始平移手势,则滚动视图将无法垂直滚动.

代码

下面是初始化 collection 视图的代码:

- (UICollectionView *)collectionView {
    if (!self->_collectionView) {
        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        layout.minimumInteritemSpacing = 10;
        layout.minimumLineSpacing = 10;
        
        layout.sectionInset = UIEdgeInsetsMake(0, 16, 0, 16);
        layout.sectionInsetReference = UICollectionViewFlowLayoutSectionInsetFromContentInset;
        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        
        self->_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
        self->_collectionView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_collectionView.backgroundColor = nil;
        self->_collectionView.delegate = self;
        self->_collectionView.dataSource = self;
        
        [self.collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"MyCollectionViewCell"];
    }
    return self->_collectionView;
}

问题

有谁知道为什么 collection 视图在只有一两个项目时会消耗垂直平移手势,或者如何解决这个问题?

三个视图实际上都是滚动视图。 UITableViewUICollectionView 类 继承自 UIScrollView

UIScrollView 通过其 panGestureRecognizer.

识别滚动

由于您没有在滚动视图中定义这些识别器之间的依赖关系,触摸事件将按以下方式使用:

  • 所有识别器都接收触摸(这就是它们由 UIScrollView 预先配置的方式)
  • 如果命中测试视图的识别器没有失败,它会处理平移手势
  • 如果失败,父视图的识别器会尝试处理手势。

并且这个级联的平移处理像那样沿着视图层次上升,直到手势被处理或者没有更多的滚动视图。

在您的情况下,当集合视图的内容大小小于或等于其边界大小时,水平滚动的集合视图的平移识别器对于垂直滚动不会失败。

你可以尝试两件事。要么要求滚动视图平移识别器失败以用于集合视图平移识别器

[self->_collectionView.panGestureRecognizer requireGestureRecognizerToFail:scrollView.panGestureRecognizer]

或在内容大小小于边界时禁用集合视图的滚动。为此,您可以创建 UICollectionView 的子类,覆盖 setContentSize:setBounds: 方法并相应地分配 scrollEnabled。然后使用你的子类而不是香草 UICollectionView.