从UICollectionView获取单元格的屏幕位置

Joe*_*pin 48 ios uicollectionview uicollectionviewcell

这不是一个问题,而是解释如何解决这个问题.

首先要意识到的是,它UICollectionView确实继承了UIScrollView- 所以使用滚动视图的内容进行标准查找是最好的解决方案.

这是我要解决的问题:

我有一个UICollectionView在每个细胞中都有不同的项目 - 以及不同类型的细胞.我需要选择一个单元格,以使单元格中的图像效果显示为扩展并占据整个屏幕.我如何进行扩展是另一篇文章.

挑战在于让细胞在屏幕上的位置,以便动画部分具有从哪里开始的参考点.

因此,为了便于获取此信息,请考虑以下代码:

第一点:

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's 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's location on the current screen...  You do this by getting the contentOffset
        // from the collectionView subtracted from the cell's 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's 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...
Run Code Online (Sandbox Code Playgroud)

希望这有助于其他人试图弄清楚如何在一个确切的位置上重叠某些东西等等......

小智 75

-(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);
}
Run Code Online (Sandbox Code Playgroud)

它适合我.你可以尝试自己


eli*_*o.d 41

那么问题的第一部分是非常明确的,第二部分?无论如何,如果您想要获得的是您的集合中选择单元格的框架,您可以使用:

UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath];
CGRect cellRect = attributes.frame;
Run Code Online (Sandbox Code Playgroud)

更多信息在这里


Oha*_*adM 18

@Alivin解决方案使用layoutAttributesForItemAtIndexPath工作但仅适用于用户看到的呈现/当前滚动视图.

这意味着,如果您选择第一个显示的可见单元格,您将获得实际的单元格frame,如果您滚动,frame则会产生偏差,您将无法获得所需的坐标.

这就是你需要使用convertPoint:toView的原因:

let realCenter = collectionView.convertPoint(cell.center, toView: collectionView.superview)
Run Code Online (Sandbox Code Playgroud)

基本上这个方法在一个视图中获取一个点(cell.center)并将该点转换为另一个视图(collectionView.superview)坐标系统,这正是我们所需要的.

因此,realCenter将始终包含实际所选单元格的坐标.

  • 你先生,应该赢得奖励. (4认同)

小智 7

我之前也做过这个.花了一段时间但是有可能.

你需要使用

[currentImageView.superview convertRect:currentImageView.frame toView:translateView]
Run Code Online (Sandbox Code Playgroud)

其中currentImageView是用户点击的图像.它的超级视图将是细胞.您希望将图像的矩形转换为实际位于不同视图的位置.该视图在此处称为"translateView".

什么是translateView?在大多数情况下,它只是self.view.

这将为您的imageview提供一个新的框架,以满足您的图像在桌面上的位置.完成后,您可以展开图像以占据整个屏幕.

这是我用来点击图像然后展开图像并显示允许平移图像的新控制器的代码的要点.

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