Getting cell screen location from UICollectionView

This is not so much a question as an explanation of how to solve this problem.

The first thing to understand is that UICollectionView inherits from UIScrollView , so the best solution is to use a standard search with a scroll list.

Here is the problem I was handling:

I had a UICollectionView that had different elements in each cell - along with different types of cells. I need a cell selection to trigger the effect of the image in the cell so that it expands and captures the entire screen. Like I did an extension for another post.

The task was to get the position of the cell on the screen so that the animation section had a control point from where to start.

So, to make it easier to get this information, consider the following code:

First note:

 UICollectionView *picturesCollectionView; DrawingCell cell; // -> instanceof UICollectionViewCell with custom items. // first, get the list of cells that are visible on the screen - you must do this every time // since the items can change... This is a CRITICAL fact. You do not go through the // entire list of cells - only those the collectionView indicates are visible. Note // there are some things to watch out for - the visibles array does not match the indexPath.item // number - they are independent. The latter is the item number overall the cells, while // the visibles array may have only 2 entries - so there is NOT a 1-to-1 mapping - keep // that in mind. NSArray *visibles = [self.picturesCollectionView visibleCells]; // now, cycle through the times and find the one that matches some criteria. In my // case, check that the cell for the indexPath passed matches the cell imageView... // The indexPath was passed in for the method call - note that the indexPath will point // to the number in your datasource for the particular item - this is crucial. for (int i=0; i<visibles.count; i++) { DrawingCell *cell = (DrawingCell *)visibles[i]; if (cell.imageView.image == (UIImage *)images[indexPath.item]) { // at this point, we've found the correct cell - now do the translation to determine // what is it location on the current screen... You do this by getting the contentOffset // from the collectionView subtracted from the cell origin - and adding in (in my case) // the frame offset for the position of the item I wish to animate (in my case the // imageView contained within my custom collection cell... CGFloat relativeX = cell.frame.origin.x - self.picturesCollectionView.contentOffset.x + cell.imageView.frame.origin.x; CGFloat relativeY = cell.frame.origin.y - self.picturesCollectionView.contentOffset.y + cell.imageView.frame.origin.y; // I now have the exact screen coordinates of the imageView - so since I need this // to perform animations, I save it off in a CGRect - in my case, I set the size // exactly to the size of the imageView - so say you were doing a Flicker display // where you wanted to grow a selected image, you get the coordinates of the image // in the cell and the size from the displayed image... UIImageView *image = cell.imageView; // selectedCell is a CGRect that global for the sake of this code... selectedCell = cell.frame; selectedCell.origin.x = relativeX; selectedCell.origin.y = relativeY; selectedCell.size.width = cell.imageView.frame.size.width; selectedCell.size.height = cell.imageView.frame.size.height; } } // done. I have my coordinates and the size of the imageView I wish to animate and grow... 

Hope this helps other people trying to figure out how to say, lay something on the cell in the exact place, etc.

+43
ios uicollectionview uicollectionviewcell
Feb 06 '13 at 19:28
source share
5 answers
 -(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); } 

This works for me. You can try yourself.

+61
Sep 07 '13 at 13:33
source share

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

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

More here

+39
Feb 06 '13 at 19:42
source share
Decision

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

Value, if you select the visible cells first , you will get the actual frame , but if you scroll through the list, frame will have a deviation and you will not get the required coordinates.

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 converts that point to another coordinate system (collectionView.superview), which is exactly what we need.

That way, realCenter will always contain the coordinates for the actual selected cell.

+11
Dec 24 '15 at 9:39
source share

I have done this before. it took some time, but it is possible.

You need to use

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

If currentImageView is an image that the user is deleting. This supervisor will be a cell. You want to convert the rectangle of your image to where it actually is in another view. This view is called a "translateView" here.

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

This will give you a new frame for your image, which will meet where your image is on your desk. After that, you can expand the image to display the entire screen.

Here is the gist of the code that I use to touch the image, then expand the image and display a new controller that allows you to pan the image. Strike>

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

+6
Feb 15 '13 at 23:19
source share

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

I assume that the touch event will start all this, so it will allow us to implement something meaningful;

  //First, trap the event in the collectionView controller with; - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ // lets ensure it 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 for a happy hour, do not forget to read on;

  <UICollectionViewDelegate> (hint - it needed) 
+1
Jul 03 '13 at 2:54 on
source share



All Articles