Sasha Prent
Sasha Prent

Reputation: 1171

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

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

Upvotes: 63

Views: 49105

Answers (11)

ndr.hax
ndr.hax

Reputation: 625

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
    }

Upvotes: 1

Md. Ibrahim Hassan
Md. Ibrahim Hassan

Reputation: 5467

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)

Upvotes: 0

Fidel López
Fidel López

Reputation: 1032

Swift 4

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

Upvotes: 0

James Rochabrun
James Rochabrun

Reputation: 4377

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

Upvotes: 0

Bobj-C
Bobj-C

Reputation: 5426

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

Upvotes: 26

MCR
MCR

Reputation: 1643

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

Upvotes: 41

Alexander Khitev
Alexander Khitev

Reputation: 6851

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

Upvotes: 6

Jlam
Jlam

Reputation: 1920

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.

Upvotes: 33

micantox
micantox

Reputation: 5616

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);

Upvotes: 41

DarkoM
DarkoM

Reputation: 335

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

}

Upvotes: 8

s1m0n
s1m0n

Reputation: 7685

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.

Upvotes: 2

Related Questions