Getting the screen location of a cell from a UICollectionView

-(void)collectionView:(UICollectionView *)cv didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
{

UICollectionViewLayoutAttributes *attributes = [cv layoutAttributesForItemAtIndexPath:indexPath];

CGRect cellRect = attributes.frame;

CGRect cellFrameInSuperview = [cv convertRect:cellRect toView:[cv superview]];

NSLog(@"%f",cellFrameInSuperview.origin.x);
}

It work for me.You can try yourself


Well the first part of your question is pretty much clear, the second one?? anyway if what you want to get is the frame of the select cell in your collection you can use this :

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

More info here


@Alivin solution using layoutAttributesForItemAtIndexPath works but only for the presented/current scroll view that the user sees.

Meaning, if you select the first presented visible cells you will get the actual frame, but if you scroll, the frame will have a deviation and you won't get the coordinates you need.

This is why you need to use convertPoint:toView :

let realCenter = collectionView.convertPoint(cell.center, toView: collectionView.superview)

Basically this method takes a point (cell.center) in one view and convert that point to another view (collectionView.superview) coordinate system which is exactly what we need.

Thus, realCenter will always contain the coordinates to the actual selected cell.


I've done this before as well. it took a while but it is possible.

You need to use

[currentImageView.superview convertRect:currentImageView.frame toView:translateView]

Where currentImageView is the image that the user taps. It's superview will be the cell. You want to convert the rect of your image to where it actually is on a different view. That view is called "translateView" here.

So what is translateView? In most cases it is just self.view.

This will give you a new frame for your imageview that will meet where your image is on your table. Once you have that you can expand the image to take up the entire screen.

Here is a gist of the code I use to tap an image then expand the image and display a new controller that allows panning of the image.

https://gist.github.com/farhanpatel/4964372


I needed to know the exact location of the cell's center that a user tapped relative to the UIWindow. In my situation the collectionView was a child of a view that took up 2/3 of the screen and its superview was a child of another view. Long story short using the collectionView.superView wasn't suffice and I needed the window. I used Ohadman's answer above and this answer from TomerBu to get the tapped location of the screen/window's coordinate system.

Assuming your app has 1 window that it isn't connected across multiple screens, I used both of these and the same exact location printed out.

It's important to know that this is going to give you the exact middle of the cell (relative to the window). Even if you touch the top, left, bottom or right side of the cell it's going to return the coordinate of the center of the cell itself and not the exact location that you tapped.

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    guard let cell = collectionView.cellForItem(at: indexPath) as? YourCell else { return }
    guard let layoutAttributes = collectionView.layoutAttributesForItem(at: indexPath) else { return }
    guard let window = UIApplication.shared.keyWindow else { return }

    let touchedLocationInWindow = collectionView.convert(cell.center, to: window)
    print("OhadM's version: \(touchedLocationInWindow)")

    let cPoint = layoutAttributes.center
    let tappedLocationInWindow = collectionView.convert(cPoint, to: window)
    print("TomerBu's version: \(tappedLocationInWindow)")
}