UICollectionView - Horizontal scroll, horizontal layout?
I have a UIScrollView
that lays out a grid of icons. If you were to imagine the layout for the iOS Springboard, you'd be pretty close to correct. It has a horizontal, paged scroll (just like Springboard). However, it appears that the layout is not quite right. It appears as though it is laying out the items from top to bottom. As a result, my last column only has 2 rows in it, due to the number of items to be displayed. I'd rather have my last row on the last page have 2 items, like you would see in the Springboard.
How can this be accomplished with UICollectionView
and its related classes? Do I have to write a custom UICollectionViewFlowLayout
?
Have you tried setting the scroll direction of your UICollectionViewFlowLayout to horizontal?
[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
And if you want it to page like springboard does, you'll need to enable paging on your collection view like so:
[yourCollectionView setPagingEnabled:YES];
1st approach
What about using UIPageViewController
with an array of UICollectionViewControllers
? You'd have to fetch proper number of items in each UICollectionViewController
, but it shouldn't be hard. You'd get exactly the same look as the Springboard has.
2nd approach
I've thought about this and in my opinion you have to set:
self.collectionView.pagingEnabled = YES;
and create your own collection view layout by subclassing UICollectionViewLayout
. From the custom layout object you can access self.collectionView
, so you'll know what is the size of the collection view's frame
, numberOfSections
and numberOfItemsInSection:
. With that information you can calculate cells' frames
(in prepareLayout
) and collectionViewContentSize
. Here're some articles about creating custom layouts:
- https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html
- http://www.objc.io/issue-3/collection-view-layouts.html
3rd approach
You can do this (or an approximation of it) without creating the custom layout. Add UIScrollView
in the blank view, set paging enabled in it. In the scroll view add the a collection view. Then add to it a width constraint, check in code how many items you have and set its constant
to the correct value, e.g. (self.view.frame.size.width * numOfScreens)
. Here's how it looks (numbers on cells show the indexPath.row
): https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov If you're not satisfied with the way cells are ordered, then I'm afraid you'd have to go with 1. or 2.
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.
If you are defining UICollectionViewFlowLayout
in code, it will override Interface Builder configs. Hence you need to re-define the scrollDirection
again.
let layout = UICollectionViewFlowLayout()
...
layout.scrollDirection = .Horizontal
self.awesomeCollectionView.collectionViewLayout = layout