2

我有一个与 collectionView 大小相同的垂直方向单元格,我设置了collectionView.isPagingEnabled = true. 屏幕上一次只有 1 个活动的可见单元格:

layout.scrollDirection = .vertical
collectionView.isPagingEnabled = true

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

    // collectionView is the same width and height as the device

    let width = collectionView.frame.width
    let height = collectionView.frame.height
    return CGSize(width: width, height: height)
}

我需要知道用户上下滑动后整个单元格何时出现在屏幕上(当页面完成分页并在屏幕上居中时)。或者换句话说,我需要知道用户何时不在单元格之间滑动或拖动。我试过这个:

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    if decelerate {
            
        if scrollView.frame.height == collectionView.frame.height {
                
           let indexPaths = collectionView.indexPathsForVisibleItems
           for indexPath in indexPaths {

                if let cell = collectionView.cellForItem(at: indexPath) as? MyCell {
                    print("currentCell: \(indexPath.item)") // do something in cell
                }
            }
        }
    }
}

我遇到的问题是即使我拖动 1/2 方式,这意味着如果我在第 2 项上,将 1/2 拖动到第 3 项,然后拖回第 2 项,然后会print("currentCell: \(indexPath.item)")打印出来。它应该打印的唯一时间是该单元格是否完全在屏幕上,而不是在单元格 2 和 3(或 2 和 1 等)之间。currentCell: 3currentCell: 2currentCell: 3

4

2 回答 2

2

你可以尝试这样的事情:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let y = targetContentOffset.pointee.y
    let item = Int(y / view.frame.height)
    print("current cell: \(item)")
}

在这段代码中,我使用框架的宽度来划分 x,因为我的 collectionView 是水平的,您可以使用高度作为垂直轴。希望能帮助到你

于 2020-06-24T09:06:55.970 回答
0

你可以使用:

var currentCellIndexPath: IndexPath? = nil {
   didSet {
      guard oldValue != currentCellIndexPath else { return }
      // Get the cell
   }
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
     let ratio = scrollView.contentOffset.y / scrollView.contentSize.height
     let candidate = ratio.rounded()
     
     guard abs(candidate - ratio) < 0.1 else { return }
     
     guard collectionView.indexPathsForVisibleItems.count > 1 else {
         guard !collectionView.indexPathsForVisibleItems.isEmpty else {
             return
         }

         currentCellIndexPath = collectionView.indexPathsForVisibleItems[0]
     }

     let firstIdx = collectionView.indexPathsForVisibleItems[0]                    
     let secondIdx = collectionView.indexPathsForVisibleItems[1]

     if candidate > ratio {
        currentCellIndexPath = secondIdx > firstIdx ? secondIdx : firstIdx
     } else {
        currentCellIndexPath = secondIdx > firstIdx ? firstIdx : secondIdx
     }
        
}

另一种解决方案,对于您的情况,您在 collectionView.indexPathsForVisibleItems 中最多有 2 个索引路径。

因此,如果有两个索引路径,您只需要检查一个正确的。您可以通过以下方式检查:

let ratio = scrollView.contentOffset.y / scrollView.contentSize.height
let isUpper = ratio - CGFloat(Int(ratio)) > 0.5

然后如果 isUpper = true,它是数组中的第二个 indexPath。

于 2020-06-24T07:16:02.257 回答