Step by Step Guide to UICollectionViewLayout

hairui lin
5 min readOct 25, 2018

--

If you have just started to pick up iOS programming for not too long, I believe most of the people would advice you against understanding too much of UICollectionViewLayout because UICollectionViewFlowLayout will, under most circumstances, be sufficient for what you need.

The reason for such an advice is simple: UICollectionViewLayout can be rather complicated. But don’t let the world “complicated” scared you away. UICollectionViewLayout can be complicated but it Is definitely not difficult.

1.Pre-Requisite

You need to have at least a good understanding of the following subjects to understand the guide

  • Frame
  • CollectionView (Delegate and DataSource)

2. Introduction

In essence, UICollectionViewLayout is just a class object that takes the responsibility of arranging the child views of a UICollectionView. But in UICollectionView world, we call the child views Cell and we set the views through a wrapper class called UICollectionViewLayoutAttributes. Whenever you set the frame property of the UICollectionViewLayoutAttributes, you are essentially setting the frame of the cell.

There are other attributes in UICollectionViewLayoutAttributes besides frame. But you should understand how to use them without me explaining much after this tutorial.

3. Unfolding The Magic In UICollectionViewFlowLayout

3.1 Adding Four Boxes

If i am to ask you to add four boxes onto the main view of a view controller, so that they are arranged exactly as shown in Fig.1 below

Fig.1

How would you do it in the most brute force and un-elegant way?

I think most of the us will come up with, more or less, the same kinda codes below

But now if you really think about the four boxes we have added to the main view, doesn’t the design, or the layout, resembles a lot of how UICollectionView will layout four cells of the same size if its UICollectionViewLayout is UICollectionViewFlowLayout?

The only difference is that, if we are to add a few more boxes to our main view, we need to manually write the codes for all the boxes added (Initialisation & position codes) while for UICollectionView, it will just automatically lay out the added boxes(or cells) in the same way but without the need of anymore Initialisation & position codes.

Initialisation codes reside in cellForItem datasource method, while the position codes reside in UICollectionViewLayout class.

So what is the catch? The catch is that UICollectionViewFlowLayout must contain a generic function that is capable of calculating the position of its child views (cells) correctly regardless how many these child views there are. Therefore, if we are to write a UICollectionViewFlowLayout class on our own, all we have to do is to generalise the pattern of how these boxes will be placed and write a function to produce these positional codes of our child views.

That being said, if we are able to write a function to generalise the pattern of how boxes should be placed in the main view, we can achieve the same result in main view as a UICollectionView with a UICollectionViewLayout.

If you now paste this piece of code in your view controller, you can specify any number of boxes you want to be displayed in the main view and they will be layout nicely just like in a collection view with UICollectionViewFlowLayout.

3.2 Conclusion

UICollectionViewLayout is no magical object and what it does is actually very simple. It merely provides a generic way of calculating the position of CollectionView’s child views (cells).

It is like refactor the codes in addBoxes(_ number) function to a separate class. That is it.

4.Difference Between UICollectionViewLayout & UICollectionViewFlowLayout

I have been talking about UICollectionViewLayout but using UICollectionViewFlowLayout as an example. So before any confusion arises, i would just like to point out the difference between two, or rather, the connection between them.

UICollectionViewFlowLayout is a subclass of UICollectionViewLayout. Ok? But what does that actually mean?

UICollectionViewLayout, being the super class, is merely a skeleton, requesting us to conform to the ways in how we put and retrieve our positional codes. And it has three functions and one property to arrange the positional codes.

  1. Prepare() — function
  2. CollectionViewContentSize — Property
  3. layoutAttributesForElements(in rect)
  4. layoutAttributesForItem(at indexPath)

in UICollectionViewLayout, all these functions and property do nothing. For example, layoutAttributesForElements(in rect) return nils in UICollectionViewLayout. UICollectionViewLayout is waiting for someone to subclass it and provide the appropriate content.

UICollectionViewFlowLayout is a concrete class of UICollectionViewLayout that has all its four members implemented, in the way that the cells will be arranged in a grid manner.

5. Re-Implementing UIColllectionViewFlowLayout

Now, if I have convinced you that UICollectionViewLayout is not difficult at all, then we can start to implement a custom flow layout. But instead of implementing a fanciful layout, i am going to re-implement the UICollectionViewFlowLayout.

To show you the possible underline codes in UICollectionViewFlowLayout implemented by Apple Engineers.

5.1.Delegate Methods To Get Size

Before we really start implementing our UICollectionViewLayout, we need to define a few protocols to get the data we want. In this case, the size of the cell.

You can see that UICollectionViewDelegateFlowLayout has, too, several delegate methods to get the data it needs for its layout. In the original UICollectionViewFlowLayout, when we set the CollectionView’s delegate, iOS automatically helps us to set the CollectionView’s delegate as its FlowLayout’s delegate .

But since we don’t have the luxury of accessing the underling codes of UICollectionView, we set the CustomCollectionViewLayoutDelegate manually in ViewController

Before we start implementing Prepare(), let’s define some properties for our CustomCollectionViewLayout class.

This is quite self-explanatory, so i am not going to explain the codes.

5.2 Prepare()

This is the function that is called before everything else. It is the place where your positional codes should go to. There are two main things you need to do in here.

  1. Calculate the contentSize of UICollectionView
  2. Calculate the positions of each cell. (This will be wrapped in UICollectionViewLayoutAttributes)

Prepare() is a place where i do all our calculations and put the individual cell’s attributes to property cache to be retrieved whenever they need it.

5.3 LayoutAttributesForElement & layoutAttributesForItem

After prepare() function, the rest is quite trivial. In the sense that all we need to do is to access cache to get the corresponding UICollectionViewLayoutAttributes that we need.

Now, if you set up a collectionView in a viewController and set its UICollectionViewLayout as CustomCollectionViewLayout, you will be able to see that the boxes being lay out in grid manner (set backgroundColor of the cell to be random color to see the result).

6. Extra Notes

In this example, i did not include things such as padding, insets and other stuffs that UICollectionViewFlowLayout. But if you are able to get the gist of it. It should be rather simple for you to add in properties such as minimumLineSpacing, minimumIterItemSpacing and all those stuffs.

7. Conclusion

Hopefully i have done a somewhat ok job in explaining UICollectionViewLayout and reducing your fear for it.

Cheers.

--

--