Swift

Compositional Layout in UICollectionView

I had a lot of fun when explore the new API so I decided to make a post to share with you guys what I’ve learned. Let’s get started.

Updated:

I’ve created a instagram-like layout using Compositional Layout. You can check it out here:

https://github.com/LearnWithTung/InstagramGridLayout

A boring introduction (but it’s worth to read)

Compositional Layout has been introduced in WWDC 2019 event which contains a lot of power that helps developer build more complex collection layout but much less code.

On the one hand, if you just need a simple layout like a collection of identical items UICollectionViewFlowLayout is the best candidate for the job, it’s simple, it’s easy to implement. On the other hand, if you need more complex layout (I think most of the app nowadays), before Compositional Layouts you’ll need to create your own custom layout by subclass a bunch of classes, calculate rows, cells and stuff which is not easy to implement.

But Compositional Layout come to save. Now it becomes much easier to us to build whatever layout we wanted. Only thing I’m very sorry to say is it only support iOS 13.0 or above.

Advantages:

  • Composable
  • Flexible
  • Fast

Disadvantages:

  • Only support iOS13.0 or above.

Now let take a look under the hood to better understand how it works.

Compositional Layouts: Under the Hood

Image for post
Hierarchy of a compositional layout

Compositional Layout compose small layout groups together as you can see in the photo above. A layout consists of sections. Each section consists of groups, every group consists of items .

Core Concepts

To build any compositional layout, the following four classes need to be implemented:

  • NSCollectionLayoutSize — The width and height dimensions are of the type NSCollectionLayoutDimension which can be defined by setting the fractional width/height of the layout (percentage relative to its container), or by setting the absolute or estimated sizes.
  • NSCollectionLayoutItem — This is your layout’s cell that renders on the screen based on the size.
  • NSCollectionLayoutGroup — It holds the NSCollectionLayoutItem in either horizontal, vertical, or custom forms.
  • NSCollectionLayoutSection — This is used to initialize the section by passing along the NSCollectionLayoutGroup. Sections eventually compose the compositional layouts.

Notice that all the classes above have prefix NS not UI. That’s because the new API is universal API which can be use not just on iOS but MacOS, WatchOS, iPadOS.

Interesting Implementation Code

Horizontal paging layout

Take a look at the snippet of code bellow :

init(){
     let layout = UICollectionViewCompositionalLayout { (section, env) -> NSCollectionLayoutSection? in
         // 1
         let item = NSCollectionLayoutItem(layoutSize:   .init(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(200)))
         // 2
         let group = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(200)), subitems: [item])
         // 3
         let section = NSCollectionLayoutSection(group: group)
         return section
    }
    super.init(collectionViewLayout: layout) 
}
  • 1. Declare item with size.fractionalWidth(1.0) means items will take up full width of its container which is the group. absolute(200) means items are 200 point height.
  • 2. The group will take up full width of the section and 200p height. It holds a list of items and because we want to build a horizontal list of item so we use horizontal class function.
  • 3. Lastly, we initialize section contain the group created above.

Just few lines of code. Everything seem correct but if you run your application, this is what we got:

Image for post

It’s a bit hard to see, so add this line of code bellow the line we declared let item

item.contentInsets = .init(top: 10, leading: 10, bottom: 10, trailing: 10)

Run your application again:

Image for post

Uhm… It layouts vertically instead of horizontally, why is that ? Behind the scene the section create 3 group instead of one. Each row you see on your screen is a group, and each group contains an item. That’s because section always try to keep items inside its frame by default. To tell section scroll horizontally we need to add this line of code bellow where you declare section:

section.orthogonalScrollingBehavior = .continuous

Run your application, now we get what we expected:

Image for post

Conclusion

This article is a bit long so I decided to split it into multiple parts, we’ll build a really interesting layout in the next part. So if you want to get more about don’t forget to follow me 😉 (and sorry for my poor english).

Compositional Layout is a very powerful API. I’m very glad that it’s been released. Throughout this introduction article I hope you guys enjoy it and understand the basic concept of how Compositional Layout works. See you in the next part.

Learn more & References

https://developer.apple.com/videos/play/wwdc2019/215

https://medium.com/better-programming/ios-13-compositional-layouts-in-collectionview-90a574b410b8

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *