How to center a UICollectionView when it is tapped

2019-03-11 05:34发布

问题:

I have a UICollectionView and it has quite a lot of UICollectionViewCells on it. I want to scroll the cell to the centre of the UICollectionView when it is tapped. My concern is that even if I tap the last or the top cell it should move to the centre of the collection view.

I have tried setting the contentInsets and offsets but they don't seem to work. I think I will have to change the content size on selection and change it back to original when the scrolling begins.

回答1:

Setting contentInsets should give some extra space around first and last cells:

CGFloat collectionViewHeight = CGRectGetHeight(collectionView.bounds);
[collectionView
  setContentInset:
   UIEdgeInsetsMake(collectionViewHeight/2, 0, collectionViewHeight/2, 0) ];
  // nb, those are top-left-bottom-right

After you should call:

[collectionView scrollToItemAtIndexPath:selectedItemPath
    atScrollPosition:UICollectionViewScrollPositionCenteredVertically
    animated:YES];

It's important to pass correct scroll position: UICollectionViewScrollPositionCenteredVertically

This should center tapped item properly.

EDIT

It's really strange, but after setting UIEdgeInsets to collection view method scrollToItemAtIndexPath does not works properly, so i make some modification:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat collectionViewHeight = CGRectGetHeight(self.collectionView.frame);
    [collectionView setContentInset:UIEdgeInsetsMake(collectionViewHeight / 2, 0, collectionViewHeight / 2, 0)];

    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    CGPoint offset = CGPointMake(0,  cell.center.y - collectionViewHeight / 2);
    [collectionView setContentOffset:offset animated:YES];
}

it works fine for me.



回答2:

It seems that this bug is caused by a bad interaction between the scroll view's contentInset and UICollectionViewFlowLayout. In my testing, setting layout.sectionInset rather than collectionView.contentInset eliminated the problem.

Based on the accepted answer above, I would eliminate the workaround, and change:

[collectionView setContentInset:UIEdgeInsetsMake(collectionViewHeight / 2, 0, collectionViewHeight / 2, 0)];

to

[layout setSectionInset:UIEdgeInsetsMake(collectionViewHeight / 2, 0, collectionViewHeight / 2, 0)];


回答3:

Swift 3 solution for scrolling and centering screen to make the tapped item visible:

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
}

This doesn't add inset above or under the collectionView!



回答4:

You can use scrollToItemAtIndexPath method to put selected(tapped) cell to center position in UICollectionView

[collectionView scrollToItemAtIndexPath:indexPath
                       atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                               animated:true];

You can use UICollectionViewScrollPositionCenteredVertically for vertical centered position