简体   繁体   English

使用 collectionView.isPagingEnabled = true 如何知道分页何时完成

[英]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 .我有一个与 collectionView 大小相同的垂直方向单元格,并且我设置了collectionView.isPagingEnabled = true There is only 1 active visible cell on screen at a time:屏幕上一次只有 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)
}

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

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.在这段代码中,我使用框架的宽度来划分 x,因为我的 collectionView 是水平的,您可以使用高度作为垂直轴。 Hope it helps希望能帮助到你

you could use:你可以使用:

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

Another solution, for your case, you have maximum 2 index paths in collectionView.indexPathsForVisibleItems.另一种解决方案,对于您的情况,您在 collectionView.indexPathsForVisibleItems 中最多有 2 个索引路径。

so all you need is check what is correct one if there're two index paths.因此,如果有两个索引路径,您只需要检查一个正确的。 you can check by:您可以通过以下方式检查:

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

then if isUpper = true, it's the second indexPath in array.然后如果 isUpper = true,它是数组中的第二个 indexPath。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM