【问题标题】:Detecting closest collectionviewcell to the center of the collectionview检测离collectionview中心最近的collectionviewcell
【发布时间】:2015-10-01 01:55:37
【问题描述】:

怀疑我在下面做一些根本错误的事情......我有一个水平的集合视图,拖动后我想将最近的单元格捕捉到中心。但是我的结果是不可预测的......我在这里做错了什么?

    func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    // Find collectionview cell nearest to the center of collectionView
    // Arbitrarily start with the last cell (as a default)
    var closestCell : UICollectionViewCell = collectionView.visibleCells()[0];
    for cell in collectionView!.visibleCells() as [UICollectionViewCell] {
        let closestCellDelta = abs(closestCell.center.x - collectionView.bounds.size.width/2.0)
        let cellDelta = abs(cell.center.x - collectionView.bounds.size.width/2.0)
        if (cellDelta < closestCellDelta){
            closestCell = cell
        }
    }
    let indexPath = collectionView.indexPathForCell(closestCell)
    collectionView.scrollToItemAtIndexPath(indexPath!, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
}

【问题讨论】:

    标签: ios uicollectionview uicollectionviewcell


    【解决方案1】:

    原来我的原始代码没有考虑到 collecitonview 内容偏移量。此外,我将居中移到了 scrollViewDidEndDecelerating 回调中。我已经修改了原始代码并将其包含在下面。

        func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
        // Find collectionview cell nearest to the center of collectionView
        // Arbitrarily start with the last cell (as a default)
        var closestCell : UICollectionViewCell = collectionView.visibleCells()[0];
        for cell in collectionView!.visibleCells() as [UICollectionViewCell] {
            let closestCellDelta = abs(closestCell.center.x - collectionView.bounds.size.width/2.0 - collectionView.contentOffset.x)
            let cellDelta = abs(cell.center.x - collectionView.bounds.size.width/2.0 - collectionView.contentOffset.x)
            if (cellDelta < closestCellDelta){
                closestCell = cell
            }
        }
        let indexPath = collectionView.indexPathForCell(closestCell)
        collectionView.scrollToItemAtIndexPath(indexPath!, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
    }
    

    【讨论】:

    • 你成功了... ;)
    • 关闭但不适合我。位置 1 的单元格总是被跳过以支持单元格 0 或 2。这是纵向的。在横向中,倒数第二个单元格同样受到影响。
    • 发挥了作用,不得不更新部分的插图以允许将第一个和最后一个项目居中
    • 目标c版请。
    • 我在搜索中看到了几个这样的例子,每次的答案都是scrollViewDidSomething函数参考了里面的“collectionView”。每当我尝试这个时,我都会得到“对 collectionView 的模糊使用”。你在哪里定义“collectionView”? scrollViewDidEndDecelerating 函数是否在另一个允许您引用 collectionView 的函数中?
    【解决方案2】:

    试试这个:

    NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:self.collectionView.center];
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
    

    斯威夫特:

    let indexPath = self.collectionView.indexPathForItemAtPoint(self.collectionView.center)
    self.collectionView.scrollToItemAtIndexPath(indexPath!, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
    

    【讨论】:

    • 看起来应该可以,但对我来说 indexPathForItemAtPoint 返回 nil。
    • 总是返回零?还是只在某些时候?
    • 总是...这很有趣,也许还有其他事情发生。有机会我会发布更完整的代码。
    • 当点落在单元格之间时,这里建议的解决方案确实返回 nil,所以它对我来说不是一个可行的解决方案。
    【解决方案3】:

    没有一个解决方案能可靠地为我工作,所以我写了这个并且它 100% 的时间都有效。非常简单。即使是内置的 indexPathForItemAtPoint 也不能​​ 100% 工作。

    extension UICollectionView {
        
        var centerMostCell:UICollectionViewCell? {
            guard let superview = superview else { return nil }
            let centerInWindow = superview.convert(center, to: nil)
            guard visibleCells.count > 0 else { return nil }
            var closestCell:UICollectionViewCell?
            for cell in visibleCells {
                guard let sv = cell.superview else { continue }
                let cellFrameInWindow = sv.convert(cell.frame, to: nil)
                if cellFrameInWindow.contains(centerInWindow) {
                    closestCell = cell
                    break
                }
            }
            return closestCell
        }
        
    }
    

    【讨论】:

    • 发布答案后,我意识到如果没有包含集合视图中心点的单元格,这将返回 nil。所以,只要有一个包含中心的单元格,你就会把它拿回来。
    【解决方案4】:

    Swift 4 的更新版本

    var closestCell = collectionView.visibleCells[0]
    for cell in collectionView.visibleCells {
        let closestCellDelta = abs(closestCell.center.x - collectionView.bounds.size.width/2.0 - collectionView.contentOffset.x)
        let cellDelta = abs(cell.center.x - collectionView.bounds.size.width/2.0 - collectionView.contentOffset.x)
        if (cellDelta < closestCellDelta){
            closestCell = cell
        }
    }
    
    let indexPath = collectionView.indexPath(for: closestCell)
    collectionView.scrollToItem(at: indexPath!, at: .centeredHorizontally, animated: true)
    

    【讨论】:

      【解决方案5】:
      • 停止拖动时,只需选择中心并使用它来选择索引路径

      斯威夫特 4.2

      func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
          let indexPath = photoCollectionView.indexPathForItem(at: photoCollectionView.center)
          photoCollectionView.scrollToItemAtIndexPath(indexPath!, atScrollPosition: .centeredHorizontally, animated: true)
      }
      

      【讨论】:

        【解决方案6】:
        var centerUICollectionViewCell: UICollectionViewCell? {
          get {
            // 1 
            guard let center = collectionView.superview?.convert(collectionView.center, to: collectionView) else { return nil }
        
            // 2  
            guard let centerIndexPath = collectionView.indexPathForItem(at: center) else { return nil }
        
            // 3
            return collectionView.cellForItem(at: centerIndexPath)
          }
        }
        

        1:需要确保我们将点从superview坐标空间转换到collectionView的空间

        2:使用collectionView的本地空间点查找indexPath

        3:返回 indexPath 的单元格

        【讨论】:

          猜你喜欢
          • 2016-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-06
          • 2021-12-01
          • 2013-12-23
          • 1970-01-01
          • 2018-07-02
          相关资源
          最近更新 更多