UICollectionViewLayout class is an abstract base class that you subclass and use to generate layout information for a collection view. The job of a layout object is to determine the placement of cells, supplementary views, and decoration views inside the collection view’s bounds and to report that information to the collection view when asked. The collection view then applies the provided layout information to the corresponding views so that they can be presented onscreen.
- iOS 6.0+
- tvOS 6.0+
You must subclass
UICollectionViewLayout in order to use it. Before you consider subclassing, though, you should look at the
UICollectionViewFlowLayout class to see if it can be adapted to your layout needs.
The main job of a layout object is to provide information about the position and visual state of items in the collection view. The layout object does not create the views for which it provides the layout. Those views are created by the collection view’s data source. Instead, the layout object defines the position and size of visual elements based on the design of the layout.
Collection views have three types of visual elements that need to be laid out:
Cells are the main elements positioned by the layout. Each cell represents a single data item in the collection. A collection view can have a single group of cells or it can divide those cells into multiple sections. The layout object’s main job is to arrange the cells in the collection view’s content area.
Supplementary views present data but are different than cells. Unlike cells, supplementary views cannot be selected by the user. Instead, you use supplementary views to implement things like header and footer views for a given section or for the entire collection view. Supplementary views are optional and their use and placement is defined by the layout object.
Decoration views are visual adornments that cannot be selected and are not inherently tied to the data of the collection view. Decoration views are another type of supplementary view. Like supplementary views, they are optional and their use and placement is defined by the layout object.
The collection view asks its layout object to provide layout information for these elements at many different times. Every cell and view that appears on screen is positioned using information from the layout object. Similarly, every time items are inserted into or deleted from the collection view, additional layout occurs for the items being added or removed. However, the collection view always limits layout to the objects that are visible onscreen.
Methods to Override
Every layout object should implement the following methods:
layoutAttributesForSupplementaryView(ofKind:at:)(if your layout supports supplementary views)
layoutAttributesForDecorationView(ofKind:at:)(if your layout supports decoration views)
These methods provide the fundamental layout information that the collection view needs to place contents on the screen. Of course, if your layout does not support supplementary or decoration views, do not implement the corresponding methods.
When the data in the collection view changes and items are to be inserted or deleted, the collection view asks its layout object to update the layout information. Specifically, any item that is moved, added, or deleted must have its layout information updated to reflect its new location. For moved items, the collection view uses the standard methods to retrieve the item’s updated layout attributes. For items being inserted or deleted, the collection view calls some different methods, which you should override to provide the appropriate layout information:
In addition to these methods, you can also override the
prepare(forCollectionViewUpdates:) to handle any layout-related preparation. You can also override the
finalizeCollectionViewUpdates() method and use it to add animations to the overall animation block or to implement any final layout-related tasks.
Optimizing Layout Performance Using Invalidation Contexts
When designing your custom layouts, you can improve performance by invalidating only those parts of your layout that actually changed. When you change items, calling the
invalidateLayout() method forces the collection view to recompute all of its layout information and reapply it. A better solution is to recompute only the layout information that changed, which is exactly what invalidation contexts allow you to do. An invalidation context lets you specify which parts of the layout changed. The layout object can then use that information to minimize the amount of data it recomputes.
To define a custom invalidation context for your layout, subclass the
UICollectionViewLayoutInvalidationContext class. In your subclass, define custom properties that represent the parts of your layout data that can be recomputed independently. When you need to invalidate your layout at runtime, create an instance of your invalidation context subclass, configure the custom properties based on what layout information changed, and pass that object to your layout’s
invalidateLayout(with:) method. Your custom implementation of that method can use the information in the invalidation context to recompute only the portions of your layout that changed.
If you define a custom invalidation context class for your layout object, you should also override the invalidationContextClass() method and return your custom class. The collection view always creates an instance of the class you specify when it needs an invalidation context. Returning your custom subclass from this method ensures that your layout object always has the invalidation context it expects.