I have a dataset that is divided into multiple sections, however, I'd like to display this in a collectionView without breaks between sections. Here's an illustration of what I want to achieve:
Instead of:
0-0 0-1 0-2
0-3
1-0 1-1
2-0
3-0
I want:
0-0 0-1 0-2
0-3 1-0 1-1
2-0 3-0
I realize the solution likely lies with a custom UICollectionViewLayout subclass, but I'm not sure how to achieve something like this.
Thanks
I found that for me, Marmoy's answer is missing one additional element:
overriding collectionViewContentSize.
Otherwise, depending on the size of your collectionView, you may get a call to layoutAttributesForElements(in rect: CGRect) which has a zero width or height, which will miss many of the cells. This is especially true if you're trying to dynamically size items in the collection view.
So a more complete version of Marmoy's answer would be:
Additionally, it's important for your delegate to implement UICollectionViewDelegateFlowLayout in the example above... Alternately, you can just calculate item sizes in the Layout if you know them without knowing about the cell content.
You are correct that you need to subclass UICollectionViewLayout. The essence to understand before starting is that you need to calculate at least position and size for every cell in the collection view. UICollectionViewLayout is just a structured way to provide that information. You get the structure, but you have to provide everything else yourself.
There are 4 methods you need to override:
One trick is to cache the layout attributes in a lookup table (dictionary):
In prepare, you calculate the layout attributes for each indexPath in your collectionView:
In invalidateLayout you reset the cached layout attributes and recalculate them:
In layoutAttributesForItemAtIndexPath you use the lookup table to return the right layout attributes:
In layoutAttributesForElementsInRect you filter your lookup table for the elements within the specified rect:
The final piece of the puzzle is the actual calculation of the layout attributes. Here I will provide only pseudo-code:
To answer your question, here is pseudo-code to calculate the position of each cell:
If you need your custom layout to be configurable, then either use UICollectionViewDelegateFlowLayout if the available signatures are sufficient, or define your own that inherits from UICollectionViewDelegateFlowLayout or UICollectionViewDelegate. Because your protocol inherits from UICollectionViewDelegateFlowLayout, which itself inherits from UICollectionViewDelegate, you can set it directly as the collectionView delegate in your viewcontroller. In your custom collection view layout you just need to cast the delegate from UICollectionViewDelegate to your custom protocol to use it. Remember to handle cases where the casting fails or where the protocol methods are not implemented by the delegate.