You already know how to set up a UITableView and UICollectionView. You’ve used UICollectionView’s flow layout to death, and now you’re ready to take the next step. Custom UICollectionView layouts are the most powerful tool for making your app’s data look exactly how it should. In this post, I’ll run through the steps needed to make the simplest possible layout.
An Overview of the Cycle
All custom layout classes need to extend the UICollectionViewLayout class. In UICollectionViewLayout.h you’ll notice there are several functions one could override. We really only need a few of them. The simplest ‘life cycle’ of a layout involves the following calls to overridden functions:
- This function allows you to perform any calculations that would be needed before you calculate the position and size of any cells. This function is optional, but it can be more performant to do the work ahead of time and cache it.
- This function is not optional, and it must calculate the total size that the content will occupy. Remember that UICollectionView extends UIScrollView. The value returned from this function will be assigned to our view’s contentSize property.
- Again, this function is not optional. Our implementation of this function is where we determine the position and size of all visible cells.
- The UICollectionView now has enough information to start displaying our content. No further calls are needed until the user scrolls or the controller invalidates the layout.
- If the content of the UICollectionView is changed (i.e. adding or updating rows), this function will be called to calculate the position and size of any effected cells. This function is not optional. Additionally, the layoutAttributesForSupplementaryViewOfKind and layoutAttributesForDecorationViewOfKind functions need to be implemented if your layout uses supplementary or decoration views.
If the controller or UICollectionView calls the invalidateLayout function, this whole process will start over at step 1. To be clear: you do not need to implement the invalidateLayout function.
Step 1: Prepare
Let’s look at an example of what some of these functions might look like. The prepareLayout example is pretty simple, only because the code in this function depends entirely on what your layout looks like.
Step 2: Calculate Size
The same issue applies for the collectionViewContentSize example. This implementation is totally dependent on what your layout should look like.
Step 3: Layout Cells
The layoutAttributesForElementsInRect is a little confusing because the return type is NSArray and it’s not immediately obvious that the elements in said array all need to be instances of UICollectionViewLayoutAttributes. In this example, I’ll attempt to keep it simple by having a layout without supplementary or decoration views. The implementation should look something like this:
Step 4: Sanity Check
If you’re following along, now is a good time to run the app and check to see that your cells show up where you want them.
Step 5: Layout for Index Paths
The last function we need is layoutAttributesForItemAtIndexPath. This example will exclude supplementary and decoration views, but if your layout includes those, you will need the similarly named layoutAttributesForSupplementaryViewOfKind and layoutAttributesForDecorationViewOfKind functions. As you can see, we’re just calculating the same CGRect as the layoutAttributesForElementsInRect function above.
After this function is completed, you should have a functional layout.
There are more features of UICollectionView that are not discussed in this post. Once you’re up and running with these basic layout functions, it will be easier to do experiments to see which others will be useful for you.