iosswiftuicollectionviewuiscrollviewdelegatescroll-paging

With collectionView.isPagingEnabled = true how to know when paging is completed


I have a vertical direction cell that is the same size of the collectionView and I set collectionView.isPagingEnabled = true. There is only 1 active visible cell on screen at a time:

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)
}

I need to know when the entire cell is on screen after the user swipes either up and down (when the page is finished paging and centered on screen). Or in other words I need to know when the user isn't swiping or dragging in between cells. I tried this:

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
                }
            }
        }
    }
}

The problem I ran into is even if I drag 1/2 way, meaning if I'm on item 2, drag 1/2 to item 3, then drag back to item 2, the print("currentCell: \(indexPath.item)") will print out currentCell: 3 then currentCell: 2. The only time it should print currentCell: 3 is if that cell is completely on screen and not in between cell 2 and 3 (or 2 and 1 etc).


Solution

  • You can try something like this:

    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)")
    }
    

    In this code I am using frame's width to divide x as my collectionView was horizontal, you can use height for vertical axis. Hope it helps