75

UITableView has the method rectForRowAtIndexPath:, but this does not exist in UICollectionView. I'm looking for a nice clean way to grab a cell's bounding rectangle, perhaps one that I could add as a category on UICollectionView.

Jano
  • 62,815
  • 21
  • 164
  • 192
akaru
  • 6,299
  • 9
  • 63
  • 102

5 Answers5

154

The best way I've found to do this is the following:

Objective-C

UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];

Swift

let attributes = collectionView.layoutAttributesForItem(at: indexPath)

Then you can access the location through either attributes.frame or attributes.center

simon
  • 2,635
  • 4
  • 20
  • 21
  • 17
    This will give the absolute position of the cell related to the superview `CGRect cellFrameInSuperview = [self.collectionView convertRect:attributes.frame toView:[self.collectionView superview]];` – Maverick Nov 16 '15 at 05:56
54

Only two lines of code is required to get perfect frame :

Objective-C

UICollectionViewLayoutAttributes * theAttributes = [collectionView layoutAttributesForItemAtIndexPath:indexPath];

CGRect cellFrameInSuperview = [collectionView convertRect:theAttributes.frame toView:[collectionView superview]];

Swift 4.2

let theAttributes = collectionView.layoutAttributesForItem(at: indexPath)
let cellFrameInSuperview = collectionView.convert(theAttributes.frame, to: collectionView.superview)
Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
Shaik Riyaz
  • 11,204
  • 7
  • 53
  • 70
18

in swift 3

 let theAttributes:UICollectionViewLayoutAttributes! = collectionView.layoutAttributesForItem(at: indexPath)
 let cellFrameInSuperview:CGRect!  = collectionView.convert(theAttributes.frame, to: collectionView.superview)
Waseem Sarwar
  • 2,645
  • 1
  • 21
  • 18
9

in swift you can just do:

//for any cell in collectionView
let rect = self.collectionViewLayout.layoutAttributesForItemAtIndexPath(clIndexPath).frame

//if you only need for visible cells
let rect = cellForItemAtIndexPath(indexPath)?.frame
Victor --------
  • 512
  • 1
  • 11
  • 29
-2

How about

-(CGRect)rectForCellatIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewCell *cell = [self cellForItemAtIndexPath:indexPath];

    if (!cell) {
        return CGRectZero;
    }

    return cell.frame;

}

as a category on UICollectionView?

#import <UIKit/UIKit.h>

@interface UICollectionView (CellFrame)

-(CGRect)rectForCellatIndexPath:(NSIndexPath *)indexPath;

@end


#import "UICollectionView+CellFrame.h"

@implementation UICollectionView (CellFrame)

-(CGRect)rectForCellatIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewCell *cell = [self cellForItemAtIndexPath:indexPath];

    if (!cell) {
        return CGRectZero;
    }

    return cell.frame;

}

@end
TimD
  • 8,014
  • 2
  • 24
  • 34
  • This works, but gives the cell's frame as it is within its own view hierarchy (meaning every cell will have an origin of {0,0}). I need to know what the rect is within the table view. – akaru Sep 22 '12 at 20:46
  • Use `UIView`'s `convertRect:toView:` method to convert the rect relative to the collection view. – TimD Sep 24 '12 at 12:36
  • 2
    cellForItemAtIndexPath path only returns a value for visible cells. If the cell at the indexPath is off screen it returns nil. – Ashley Mills Oct 10 '13 at 14:10
  • Works fine for visible cells, and OP did not specify visible cells or not. – phatmann Apr 15 '14 at 20:19
  • 1
    Works only for visible cells! – skywinder May 15 '14 at 11:01
  • Your solution is fine; however, I'd amend it with the convertRect:toView: method as suggested. That's for two reasons: 1) that's the only reason for getting a cell's rect in this way; 2) this is essential part of peek-and-pop functionality. That it only works for visible cells is a lame criticism from per reason #2; you will never need the rect of an offscreen cell, which is why the means to do it is not provided by any other framework. I upvoted your answer, and I intend to employ it in my current project today. – James Bush Dec 14 '16 at 23:53
  • @JamesBush, I disagree with your comment. Firstly, I would not amend it with the `convertRect:toView:` method as it's too specific and not everyone needs it. Or maybe someone needs to convert it to the `superview of the `superview` of the collection view, but you're essentially saying to assume one's view hierarchy. Secondly, you also assume people's use cases. I, for example, actually do need the rect of an off-screen cell. – Iulian Onofrei May 07 '19 at 12:45
  • this is rect for cell with parent, not collectionView, u will see x,y = 0 – famfamfam Apr 03 '21 at 08:09