Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView Horizontal Paging not centered

I have a horizontal scrolling collectionView with each cell the size of the view. When I page through the collectionView it doesn't page by cell. The cells aren't in the center of the screen. I've tried a bunch of things to try to fix it and haven't had any luck. Here's a video of the problem: https://www.youtube.com/watch?v=tXsxWelk16w Any ideas?

like image 918
mlevi Avatar asked Apr 15 '15 18:04

mlevi


People also ask

How do I make my UICollectionView scroll horizontal?

You need to reduce the height of UICollectionView to its cell / item height and select " Horizontal " from the " Scroll Direction " as seen in the screenshot below. Then it will scroll horizontally depending on the numberOfItems you have returned in its datasource implementation.

What is Uicollectionviewflowlayout?

A layout object that organizes items into a grid with optional header and footer views for each section.

What is compositional layout in Swift?

A compositional layout is a type of collection view layout. It's designed to be composable, flexible, and fast, letting you build any kind of visual arrangement for your content by combining — or compositing — each smaller component into a full layout.


2 Answers

Remove spaces between items. For horizontal scrolling collection view set minimum line spacing to 0. You can do this with interface builder or with method of UICollectionViewDelegateFlowLayout protocol:

- (CGFloat)collectionView:(UICollectionView *)collectionView                     layout:(UICollectionViewLayout *)collectionViewLayout          minimumLineSpacingForSectionAtIndex:(NSInteger)section {     return 0;     } 

enter image description here

Another way is making your cell's width less than collectionView's width for a value of horizontal space between items. Then add section insets with left and right insets that equal a half of horizontal space between items. For example, your minimum line spacing is 10:

- (CGFloat)collectionView:(UICollectionView *)collectionView                    layout:(UICollectionViewLayout *)collectionViewLayout         minimumLineSpacingForSectionAtIndex:(NSInteger)section {     return 10; }  - (CGSize)collectionView:(UICollectionView *)collectionView                    layout:(UICollectionViewLayout *)collectionViewLayout    sizeForItemAtIndexPath:(NSIndexPath *)indexPath {     return CGSizeMake(collectionView.frame.size.width - 10, collectionView.frame.size.height); }  - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView                          layout:(UICollectionViewLayout *)collectionViewLayout          insetForSectionAtIndex:(NSInteger)section {     return UIEdgeInsetsMake(0, 5, 0, 5); } 

enter image description here

And third way: manipulate collectionView scroll in scrollViewDidEndDecelerating: method:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {     if (scrollView == self.collectionView) {         CGPoint currentCellOffset = self.collectionView.contentOffset;         currentCellOffset.x += self.collectionView.frame.size.width / 2;         NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:currentCellOffset];         [self.collectionView scrollToItemAtIndexPath:indexPath                                     atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally                                             animated:YES];     } } 

enter image description here

like image 71
Vlad Avatar answered Sep 28 '22 07:09

Vlad


Demo here in Swift 3: https://github.com/damienromito/CollectionViewCustom

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {      let pageWidth = Float(itemWidth + itemSpacing)     let targetXContentOffset = Float(targetContentOffset.pointee.x)     let contentWidth = Float(collectionView!.contentSize.width  )     var newPage = Float(self.pageControl.currentPage)      if velocity.x == 0 {         newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0     } else {         newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)         if newPage < 0 {             newPage = 0         }         if (newPage > contentWidth / pageWidth) {             newPage = ceil(contentWidth / pageWidth) - 1.0         }     }     self.pageControl.currentPage = Int(newPage)     let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)     targetContentOffset.pointee = point } 

Swift 4:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {      let pageWidth = Float(itemWidth + itemSpacing)     let targetXContentOffset = Float(targetContentOffset.pointee.x)     let contentWidth = Float(collectionView!.contentSize.width  )     var newPage = Float(self.pageControl.currentPage)      if velocity.x == 0 {         newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth)) + 1.0     } else {         newPage = Float(velocity.x > 0 ? self.pageControl.currentPage + 1 : self.pageControl.currentPage - 1)         if newPage < 0 {             newPage = 0         }         if (newPage > contentWidth / pageWidth) {             newPage = ceil(contentWidth / pageWidth) - 1.0         }     }      self.pageControl.currentPage = Int(newPage)     let point = CGPoint (x: CGFloat(newPage * pageWidth), y: targetContentOffset.pointee.y)     targetContentOffset.pointee = point } 
like image 36
Paolo Musolino Avatar answered Sep 28 '22 08:09

Paolo Musolino