如何获取位于 UICollectionView 中心的单元格的 indexPath

Posted

技术标签:

【中文标题】如何获取位于 UICollectionView 中心的单元格的 indexPath【英文标题】:how to get indexPath for cell which is located in the center of UICollectionView 【发布时间】:2013-10-09 07:25:38 【问题描述】:

如何在UICollectionView 中间找到cellindexPath

我有水平滚动,只有一个大的cell 可见(部分另外两个侧面的cells 也是可见的)。 我需要删除位于中心的cell(意味着-当前cell)而不触摸它。

仅按“垃圾箱”按钮并确认删除。但现在它只删除第一个cells。

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex 
    if (buttonIndex == actionSheet.destructiveButtonIndex)  
        initialPinchPoint = ????????

        self.tappedCellPath = [self.collectionView indexPathForItemAtPoint:initialPinchPoint];

        Technique *technique = [arrayOfTechnique objectAtIndex:self.tappedCellPath.row];

        [self deleteData:[NSString stringWithFormat:@"DELETE FROM TECHNIQUES WHERE TECHNIQUENAME IS '%s'",[technique.techniquename UTF8String]]];

        [arrayOfTechnique removeObjectAtIndex:self.tappedCellPath.row];

        //[arrayOfTechnique removeObjectAtIndex:[custom_layout ]];
        [self removeImage:technique.techniquename];

        [self.collectionView performBatchUpdates:^
            [self.collectionView deleteItemsAtIndexPaths:[NSArrayarrayWithObject:self.tappedCellPath]];
          completion:nil];

         [self checkArrayCount];
    

【问题讨论】:

您可以使用集合视图的contentOffset 来计算单元格的“实际”位置。 您检查过名为 indexPathsForVisibleItems 的方法吗? 【参考方案1】:

就像你自己做的那样,indexPathForItemAtPoint 是找到你感兴趣的元素的索引路径的好方法。如果你的问题是:我怎么知道这个点的坐标?然后您应该尝试使用(使用您在代码 sn-p 中给出的相同名称):

initialPinchPoint = CGPointMake(self.collectionView.center.x + self.collectionView.contentOffset.x, 
                                self.collectionView.center.y + self.collectionView.contentOffset.y);

【讨论】:

collectionView.offset 应该是 collectionView.contentOffset 使用 contentOffset 的计算很复杂,如果您只是从 viewcontroller 的视图中心转换点,则没有必要。请参阅下面的替代答案。【参考方案2】:

这是我在 Swift 3 中所做的

private func findCenterIndex() 
    let center = self.view.convert(self.collectionView.center, to: self.collectionView)
    let index = collectionView!.indexPathForItem(at: center)
    print(index ?? "index not found")

【讨论】:

太棒了!我已经尝试了所有的解决方案,但没有一个只适用于你的【参考方案3】:

这将是更好的代码,因为它更干净,更容易阅读,所有内容偏移量计算都是多余的:

     NSIndexPath *centerCellIndexPath = 
[self.collectionView indexPathForItemAtPoint:
[self.view convertPoint:[self.view center] toView:self.collectionView]];

这也是您实际尝试做的正确表示: 1. 取 viewcontroller 视图的中心点 - 也就是视觉中心点 2.将其转换为您感兴趣的视图的坐标空间-即集合视图 3. 获取给定位置存在的索引路径。

【讨论】:

由于原始问题要求集合视图中间中的单元格,这将更正确:CGPoint centerOfScrollableContent = [self.view convertPoint:self.collectionView.center toView:self.collectionView]; 如果集合视图不是完整大小,则重要self.view. 没有@JasonMoore,如果你仔细阅读它,作者想要视觉中心 - 暗示人们正在看的视图的中心。原方案是这样的,不管collectionView的frame如何,视觉中心都正确转换。 这就是我要展示的@Jlam - 集合视图的视觉中心,但已转换为包含内容偏移量。需要centerOfScrollableContent 以确定中心的集合视图单元格:[self.collectionView indexPathForItemAtPoint:centerOfScrollableContent] me “暗示正在查看的视图的中心”,you “集合视图的中心”。我们的假设不同 - 如果集合视图原点向右偏移 20px,您的解决方案假设所需的新中心现在向右偏移 20px,我的解决方案假设所需的新中心保持不变。【参考方案4】:

斯威夫特:

extension UICollectionView 

var centerPoint : CGPoint 

    get 
        return CGPoint(x: self.center.x + self.contentOffset.x, y: self.center.y + self.contentOffset.y);
    


var centerCellIndexPath: IndexPath? 

    if let centerIndexPath: IndexPath  = self.indexPathForItemAtPoint(self.centerPoint) 
        return centerIndexPath
    
    return nil


用法:

if let centerCellIndexPath: IndexPath  = collectionView.centerCellIndexPath 
                print(centerCellIndexPath)
            

斯威夫特 3:

extension UICollectionView 

var centerPoint : CGPoint 

    get 
        return CGPoint(x: self.center.x + self.contentOffset.x, y: self.center.y + self.contentOffset.y);
    


var centerCellIndexPath: IndexPath? 

    if let centerIndexPath = self.indexPathForItem(at: self.centerPoint) 
        return centerIndexPath
    
    return nil


【讨论】:

【参考方案5】:

谢谢你micantox!

我有多个 UICollectionView 可见单元格,需要将单元格定位在集合视图的中心。类似于 Adob​​e Content Viewer 的东西。如果有人遇到类似情况:

#pragma mark - UIScrollViewDelegate methods

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    CGPoint centerPoint = CGPointMake(self.pageContentCollectionView.center.x + self.pageContentCollectionView.contentOffset.x,
                                    self.pageContentCollectionView.center.y + self.pageContentCollectionView.contentOffset.y);
    NSIndexPath *centerCellIndexPath = [self.pageContentCollectionView indexPathForItemAtPoint:centerPoint];
    [self.pageContentCollectionView scrollToItemAtIndexPath:centerCellIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];


【讨论】:

【参考方案6】:

我为水平 UICollectionView 制作了喜欢我使用 Swift 2.x。

private func findCenterIndex() 
    let collectionOrigin = collectionView!.bounds.origin
    let collectionWidth = collectionView!.bounds.width
    var centerPoint: CGPoint!
    var newX: CGFloat!
    if collectionOrigin.x > 0 
        newX = collectionOrigin.x + collectionWidth / 2
        centerPoint = CGPoint(x: newX, y: collectionOrigin.y)
     else 
        newX = collectionWidth / 2
        centerPoint = CGPoint(x: newX, y: collectionOrigin.y)
    

    let index = collectionView!.indexPathForItemAtPoint(centerPoint)
    print(index)


 override func scrollViewDidEndDecelerating(scrollView: UIScrollView) 
    findCenterIndex()

【讨论】:

【参考方案7】:

UICollectionView 有一个方法- (NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point。 此方法返回项目在指定点的索引路径。您可以计算代表UICollectionView 中心的点,然后使用该CGPoint 和此方法检索要删除的项目的索引路径。

【讨论】:

是的,我试过这个 indexPathForItemAtPoint 但它也删除了第一个项目。我会再试一次,让你知道!谢谢 第一项将被删除,因为如果该点位于 UICollectionViewCell 之外但在 UICollectionView 内,则此方法将 indexPath 返回为 nil 并且当您尝试执行“indexPath.row”之类的操作时它将返回 0 即第一个元素。因此,最佳做法是在这种情况下始终对 indexPath 进行 nil 检查。希望这会有所帮助...【参考方案8】:

对于某些在获取中心时可能遇到问题的人,请查看以下潜在解决方案:

 func centerCell()->UICollectionViewCell? 
      // Asuming your scrolling is horizontal
      let viewHorizontalCenter =  self.view.bounds.width / 2
      let center = CGPoint(x: viewHorizontalCenter, y: self.collectionView.center.y)

      let convertedPoint = self.view.convert(center, to: self.unitsCollectionView)

      let center = CGPoint(x: self.view.bounds.width / 2, y: self.unitsCollectionView.center.y)
      let convertedPoint = self.view.convert(center, to: self.unitsCollectionView)
      for cell in unitsCollectionView.visibleCells 
          if cell.frame.contains(convertedPoint) 
              print("Hello")
              return cell
          
      
      return nil
    

【讨论】:

【参考方案9】:

试试这个协议...

protocol CollectionVisibleMidCell 
extension CollectionVisibleMidCell where Self: UICollectionView 

    func getMidVisibleIndexPath() -> IndexPath? 
        var visibleRect = CGRect()
        visibleRect.origin = self.contentOffset
        visibleRect.size = self.bounds.size
        let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
        guard let indexPath = self.indexPathForItem(at: visiblePoint) else  return nil 
        return indexPath
    


extension UICollectionView: CollectionVisibleMidCell 

【讨论】:

【参考方案10】:

斯威夫特 4

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) 
    let indexPath = collectionView.indexPathForItem(at: collectionView.bounds.center)        

【讨论】:

【参考方案11】:

基于@micantox 的回答。 Swift 5

的更新代码
let initialPinchPoint = CGPoint(x: collectionView.center.x + collectionView.contentOffset.x,
                                y: collectionView.center.y + collectionView.contentOffset.y)

【讨论】:

以上是关于如何获取位于 UICollectionView 中心的单元格的 indexPath的主要内容,如果未能解决你的问题,请参考以下文章

检测位于另一个 uicollectionview 内的 uicollectionView 的哪个 UICollectionViewCell 位于中心

在 UICollectionView 中显示错误的图像

如何获取UICollectionView中选中的单元格索引

访问位于设备屏幕中心的 UICollectionView 单元格中的视图

如何在屏幕左侧显示第一部分和右侧第二部分的 UICollectionView

如何从子 UICollectionview 中获取 UITableView 的一部分