UICollectionView的UICollectionReusableView阻止/阻止UICollectionViewCell

时间:2017-05-16 16:12:20

标签: ios swift uicollectionview

我正在使用带有Flow Layout的UICollectionView。我设置了标头,这是一个UICollectionReusableView,表现得像这样;

layout?.sectionHeadersPinToVisibleBounds = true

...

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "header", for: indexPath as IndexPath)

    header.layer.zPosition = -1
    return header
}

这样可以获得所需的效果,当向上滚动单元格时,标题会保持固定但会落在常规单元格后面。

但是,如果我尝试单击向上滚动的UICollectionViewCell,即技术上覆盖UICollectionReusableView,则UICollectionViewCell的didSelectItemAt tap事件不再触发,直到我将其向下滚动远离标题所在的位置。换句话说,UICollectionReusableView阻止了点击手势,即使它的zPosition设置为-1并且不可见。

UICollectionView zIndex issue explained

有没有人遇到过这个问题,你是如何解决这个问题的?

2 个答案:

答案 0 :(得分:1)

将其添加到Section Header视图类:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    return false
}

会将所有触摸传递到下面的下一个接收器 - 在这种情况下,是您的集合视图单元格。如果在Section Header中需要交互式元素(例如按钮),则可以执行以下操作:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    let ptInSub = theButton.convert(point, from: theButton.superview)
    if theButton.bounds.contains(ptInSub) {
        return true
    }
    return false
}

这个可以给你你想要的东西,虽然......如果Cell View覆盖了Section Header上的Button,你点击按钮所在的单元格,按钮将会挖掘。应该能够用另一个contains(point)或两个......来解决这个问题。

答案 1 :(得分:0)

我最终在我的UICollectionReusableView标题中添加了Parallax效果。有一些Parallax库,但它实际上非常简单 - 我使用以下代码实现了它;

override func scrollViewDidScroll(_ scrollView: UIScrollView) {

    if header != nil {

        let scrollDiff = scrollView.contentOffset.y - self.previousScrollOffset

        let absoluteTop: CGFloat = 0;
        let absoluteBottom: CGFloat = scrollView.contentSize.height - scrollView.frame.size.height;

        let isScrollingDown = scrollDiff > 0 && scrollView.contentOffset.y > absoluteTop
        let isScrollingUp = scrollDiff < 0 && scrollView.contentOffset.y < absoluteBottom

        var newHeight = self.headerHeight
        if isScrollingDown {
            newHeight = max(self.minHeaderHeight, self.headerHeight - abs(scrollDiff))
        } else if isScrollingUp {
            newHeight = min(self.maxHeaderHeight, self.headerHeight + abs(scrollDiff))
        }

        if newHeight != self.headerHeight {
            self.headerHeight = newHeight

            self.collectionView?.contentOffset = CGPoint(x: (self.collectionView?.contentOffset.x)!, y: self.previousScrollOffset)
            self.collectionView?.collectionViewLayout.invalidateLayout()
        }

        self.previousScrollOffset = scrollView.contentOffset.y
    }

}

然后改变标题的高度(在invalidateLayout()时调用);

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

    return CGSize(width: collectionView.bounds.width, height:self.headerHeight)
}

结果是不会发生任何重叠,但它仍然会产生我想要首先实现的预期效果。