Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the screen location of a cell from a UICollectionView

People also ask

What do you mean by a value UICollectionView?

The collection view maintains a queue or list of view objects that the data source has marked for reuse. Instead of creating new views explicitly in your code, you always dequeue views. There are two methods for dequeueing views.

What is the difference between Uitableview and UICollectionView?

Tableiw is a simple list, which displays single-dimensional rows of data. It's smooth because of cell reuse and other magic. 2. UICollectionView is the model for displaying multidimensional data .


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

An alternative is to use the events to provide most if not all the answers to your questions.

I presume that a touch event will initiate all of this, so lets implement something meaningful;

  //First, trap the event in the collectionView controller with;

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

   // lets ensure it's actually visible (yes we got here from a touch event so it must be... just more info)
   if ([self.collectionView.indexPathsForVisibleItems containsObject:indexPath]) {

     // get a ref to the UICollectionViewCell at indexPath
     UICollectionViewCell *cell =(UICollectionViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];

     //finally get the rect for the cell
     CGRect cellRect = cell.frame


      // do your processing here... a ref to the cell will allow you to drill down to the image without the headache!!


  }
}

oh ... before you rush off for happy hour, lets not forget to read up on;

   <UICollectionViewDelegate> (hint - it's needed)  

SWIFTYFIED (v5) SHORT ANSWER

let attributes = collectionView.layoutAttributesForItem(at: indexPath)
let cellRect = attributes?.frame
let cellFrameInSuperview = collectionView.convert(cellRect ?? CGRect.zero, to: collectionView.superview)

All you need is the index path of the cell.