how to get indexPath for cell which is located in the center of UICollectionView

IosUicollectionviewUicollectionviewcell

Ios Problem Overview


How can i find indexPath for cell in the middle of UICollectionView?

I have horizontal scrolling and only one big cell is visible (partially two other cells on the sides are visible as well). I need to delete cell located in the center (means - current cell) without touching it.

Only pressing "Trash" button and confirm Delete. But now it delete only first 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];
    }
}

Ios Solutions


Solution 1 - Ios

Like you did yourself, indexPathForItemAtPoint is a good way of finding the index path of the element you're interested in. If your question is: how do i know the coordinates of this point? Then you should try with (using the same name you gave it in your code snippet):

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

Solution 2 - Ios

Here's what I did in 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")
}

Solution 3 - Ios

This would be better code because it's cleaner and easier to read, all the content offset calculation is superfluous:

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

This would also be the correct representation of what you're actually trying to do:

  1. Taking the center point of your viewcontroller's view - aka visual center point
  2. convert it to the coordinate space of the view you're interested in - which is the collection view
  3. Get the indexpath that exist at the location given.

Solution 4 - Ios

Swift:

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

Usage :

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

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

Solution 5 - Ios

Thank you micantox!

I had multiple visible cells of UICollectionView and needed to position the cell at the centre of the collection view. Something similar to Adobe Content Viewer. If someone is struggling with similar scenario:

#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];

}

Solution 6 - Ios

I made like for horizontal UICollectionView I use 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()
}

Solution 7 - Ios

UICollectionView has a method - (NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point.
This method return the index path of the item at the specified point. You could calculate the point that represents the center of the UICollectionView and then use that CGPoint and this method to retrieve the index path of the item you want to delete.

Solution 8 - Ios

For some of you that might be experiencing some troubles on getting the center, please look at this potential solution:

 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
    }

Solution 9 - Ios

Try this protocol...

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

Solution 10 - Ios

Swift 4

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

Solution 11 - Ios

Based on @micantox answer. Updated code for Swift 5

let initialPinchPoint = CGPoint(x: collectionView.center.x + collectionView.contentOffset.x,
                                y: collectionView.center.y + collectionView.contentOffset.y)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSasha PrentView Question on Stackoverflow
Solution 1 - IosmicantoxView Answer on Stackoverflow
Solution 2 - IosMCRView Answer on Stackoverflow
Solution 3 - IosJlamView Answer on Stackoverflow
Solution 4 - IosBobj-CView Answer on Stackoverflow
Solution 5 - IosDarkoMView Answer on Stackoverflow
Solution 6 - IosAlexander KhitevView Answer on Stackoverflow
Solution 7 - Ioss1m0nView Answer on Stackoverflow
Solution 8 - Iosndr.haxView Answer on Stackoverflow
Solution 9 - IosJames RochabrunView Answer on Stackoverflow
Solution 10 - IosFidel LópezView Answer on Stackoverflow
Solution 11 - IosMd. Ibrahim HassanView Answer on Stackoverflow