Ios 检测距离collectionview中心最近的collectionviewcell

Ios 检测距离collectionview中心最近的collectionviewcell,ios,uicollectionview,uicollectionviewcell,Ios,Uicollectionview,Uicollectionviewcell,怀疑我在下面做了一些根本错误的事情。。。我有一个水平集合视图,拖动后,我想捕捉到离中心最近的单元格。但是我的结果是不可预测的。。。我做错了什么 func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { // Find collectionview cell nearest to the center of collectionView // Arbi

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

    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)
}
func-scrollViewDiEndDraging(scrollView:UIScrollView,willDecreate-Decreate:Bool){
//查找距离collectionview中心最近的collectionview单元格
//任意从最后一个单元格开始(默认)
var closestCell:UICollectionViewCell=collectionView.visibleCells()[0];
对于collectionView!.visibleCells()中的单元格作为[UICollectionViewCell]{
让closestcelldta=abs(closestCell.center.x-collectionView.bounds.size.width/2.0)
让cellDelta=abs(cell.center.x-collectionView.bounds.size.width/2.0)
if(cellDelta
试试这个:

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)

由于CollectOnView内容偏移量的原因,我的原始代码丢失了。此外,我已经将居中移动到ScrollViewDiEndDecelling回调中。我修改了原始代码并将其包含在下面

    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)
}
func ScrollViewDiEndDecelling(scrollView:UIScrollView){
//查找距离collectionview中心最近的collectionview单元格
//任意从最后一个单元格开始(默认)
var closestCell:UICollectionViewCell=collectionView.visibleCells()[0];
对于collectionView!.visibleCells()中的单元格作为[UICollectionViewCell]{
让closestcelldta=abs(closestCell.center.x-collectionView.bounds.size.width/2.0-collectionView.contentOffset.x)
设cellDelta=abs(cell.center.x-collectionView.bounds.size.width/2.0-collectionView.contentOffset.x)
if(cellDelta
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)
var closestCell=collectionView.visibleCells[0]
对于collectionView.visibleCells中的单元格{
让closestcelldta=abs(closestCell.center.x-collectionView.bounds.size.width/2.0-collectionView.contentOffset.x)
设cellDelta=abs(cell.center.x-collectionView.bounds.size.width/2.0-collectionView.contentOffset.x)
if(cellDelta
  • 停止拖动时,只需选择中心并使用它选择索引
swift 4.2


没有一个解决方案能可靠地为我工作,所以我写了这篇文章,它在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
    }
    
}
1:需要确保我们正在将点从superview坐标空间转换为collectionView的空间

2:使用collectionView的局部空间点来查找索引


3:返回indexPath的单元格

看起来应该可以,但对我来说,indexPathForItemAtPoint返回nil。总是返回nil吗?或者只是在某些时候?总是。。。这很有趣,也许还有别的事情。如果有机会,我将发布更完整的代码。当点位于单元格之间时,此处建议的解决方案将返回零,因此这对我来说不是一个有效的解决方案。而您确定了itt…;)很接近,但对我来说不是修复。位置1处的单元格始终被跳过,以支持单元格0或2。那是画像。在景观中,倒数第二个单元格也受到了类似的影响。使用了一个符咒,必须更新部分的插图,以允许将第一个和最后一个项目居中。请使用Objective c版本。我在搜索中看到了几个这样的例子,每次都会得到一个scrollViewDidSomething函数,其中引用了“collectionView”。每当我尝试这一点时,我都会得到“collectionView的模糊使用”。您在哪里定义“collectionView”?ScrollViewDiEndDecreating函数是否在另一个允许您引用collectionView的函数中?发布答案后,我意识到如果没有包含collection view中心点的单元格,则返回nil。所以,只要有一个包含中心的单元,你就可以得到它。
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
    }
    
}
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)
  }
}