确定屏幕上水平 CollectionView 单元格的可见性百分比

Determine Percentage of Visibility of Horizontal CollectionView Cells on Screen

我有一个水平的 collectionView。总会有 2 个并排的单元格,它们的宽度和高度都相同。单元格播放视频,滚动时我想为屏幕上 70% 的下一个单元格加载视频,并停止小于该单元格的视频。我发现了几个类似的问题,但所有内容似乎都引用了 1 个单元格。

1- 单元格 59 和 60 在屏幕上都是 100%

2-向左滚动,59还在70%以上,60是100%,61在屏幕上还不到30%

3- 仍在向左滚动,59 小于屏幕的 30%,60 为 100%,61 大于 70%

任何已经可见的内容,如前两张照片中的单元格 59 和所有三张照片中的 60,我有逻辑阻止单元格再次加载,即使 cell.loadNewVideo() 将 运行为了他们。

layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let width = UIScreen.main.bounds.width / 2
    return CGSize(width: width, height: 150)
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    collectionView.visibleCells.forEach { cell in
        guard let cell = cell as? VideoCell else { continue }

        guard let indexPath = collectionView.indexPath(for: cell) else { return }
        guard let layoutAttributes = collectionView.layoutAttributesForItem(at: indexPath) else { return }
        let cellFrameInSuperview = collectionView.convert(layoutAttributes.frame, to: collectionView.superview)
        guard let superView = collectionView.superview else { return }
        let convertedRect = collectionView.convert(cellFrameInSuperview, to: superView)
        let intersect = collectionView.frame.intersection(convertedRect)

        if intersect.width > (UIScreen.main.bounds.width / 2) * 0.7 {

            cell.loadNewVideo()

        } else {

            cell.destroyOldVideo()
        }
    }
}

我也在 scrollViewWillEndDragging 中尝试了相同的代码,但它也没有用:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

}

想多了。忘记 layoutAttributes 和所有花哨的东西,只做你说的你想做的事:找出 单元格 有多少 在屏幕上.

单元格是一个视图。屏幕(比方说,由 window 表示)是一个视图。与他们相交!在适当转换的坐标中查看单元格框架与 window(或其他)的交集,以获取屏幕上的单元格部分,并将其大小与单元格框架的大小进行比较。那是你的百分比。现在做任何你喜欢的百分比。

在这个例子中,“任何你喜欢的”只是为了显示百分比。

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let cells = self.collectionView.visibleCells
    for cell in cells {
        let f = cell.frame
        let w = self.view.window!
        let rect = w.convert(f, from: cell.superview!)
        let inter = rect.intersection(w.bounds)
        let ratio = (inter.width * inter.height) / (f.width * f.height)
        let rep = (String(Int(ratio * 100)) + "%")
        let label = cell.contentView.subviews.first as! UILabel
        label.text = rep
    }
}