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?
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.
A layout object that organizes items into a grid with optional header and footer views for each section.
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.
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; }
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); }
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]; } }
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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With