UITableView used UICollectionView for the more complex view and scroll left to right or top to bottom with different presentations where we have used many other UITableViewCell and UICollectionViews. So, in WWDC 2019 apple introduce a Compositional Layout(UICollectionViewCompositionalLayout) which is used to create custom UICollectionViewLayout.
Compositional layouts create with the combination of small layout groups and convert into large complex layout groups. So it will be helpful to create a complex view because it is divided into small views. It divided into four basic building blocks, and it’s a hierarchy that consists of:
- Layout: NSCollectionLayoutSize class used for the dimension(width and height) in layout. It defined by the proportional fraction of width and height of layout or by estimated and absolutes sizes.
- Section: NSCollectionLayoutSection used to define the section for UICollectionView. Through multiple sections, it creates compositional layouts.
- Group: NSCollectionLayoutGroup used to manage the items that will scroll horizontally, vertically or numbers of items will display in the rows of the group.
- Item: NSCollectionLayoutItem used as the layout cell which extends on the screen based on the size.
Implementation of Compositional Layout:
Let’s explain the compositional layout with the examples as :
Handling Compositional Layout with Multiple Sections:
1.) Let’s create the function which returning UICollectionViewCompositionalLayout and written as :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
func createLayoutDifferentSection() -> UICollectionViewLayout { // Layout let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in var columns = 1 // Item let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0)) let item = NSCollectionLayoutItem(layoutSize: itemSize) item.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2) // Group var groupHeight = NSCollectionLayoutDimension.absolute(44) var groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: groupHeight) // Section var section = NSCollectionLayoutSection(group: NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])) switch sectionIndex{ case 7: columns = 4 groupHeight = NSCollectionLayoutDimension.fractionalWidth(0.5) groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: groupHeight) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: columns) section = NSCollectionLayoutSection(group: group) section.orthogonalScrollingBehavior = .continuous case 3,1: columns = 4 groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(0.5)) let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitem: item, count: columns) section = NSCollectionLayoutSection(group: group) section.orthogonalScrollingBehavior = .none case 2,5: columns = 3 groupHeight = NSCollectionLayoutDimension.fractionalWidth(0.6) groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: groupHeight) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: columns) section = NSCollectionLayoutSection(group: group) section.orthogonalScrollingBehavior = .continuousGroupLeadingBoundary default: columns = 1 groupHeight = NSCollectionLayoutDimension.fractionalWidth(0.6) groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.6), heightDimension: groupHeight) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: columns) section = NSCollectionLayoutSection(group: group) section.orthogonalScrollingBehavior = .groupPaging } return section } return layout } |
- Here we used the environment parameter of the section provider to customize the layout. Also NSCollectionLayoutEnvironment provides us container feature that make decisions about how we want to layout our items, groups, and sections.
- LayoutSize is an NSCollectionLayoutSize, which defined by the proportional fraction of width and height of layout or by estimated and absolutes sizes.
- The orthogonalScrollingBehavior means the section lays out its content along the main axis of its layout, defined by the layout configuration’s scrollDirection property.
- NSCollectionLayoutGroup.horizontal creates the layout group and also all items added to the group will be positioned horizontally.
- NSCollectionLayoutGroup.vertical all items added to the group will be positioned vertically.
2. ) Then add the compositional layout to our collection view, add it to the initializer, and written as:
1 2 3 4 |
collectionView.delegate = self collectionView.dataSource = self collectionView.collectionViewLayout = createLayoutDifferentSection() collectionView.reloadData() |
3.) At last, it looks like as:
Handling Compositional Layout with Nested Groups:
1.) Firstly, create the function for UICollectionViewCompositionalLayout as :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
func createNestedGroupLayout() -> UICollectionViewLayout { let bigItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.4), heightDimension: .fractionalHeight(1)) let bigItem = NSCollectionLayoutItem(layoutSize: bigItemSize) let tinyItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(0.33)) let tinyItem = NSCollectionLayoutItem(layoutSize: tinyItemSize) let nestedGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.2), heightDimension: .fractionalHeight(1)) let nestedGroup = NSCollectionLayoutGroup.vertical(layoutSize: nestedGroupSize, subitems: [tinyItem]) let mainGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(0.5)) let mainGroup = NSCollectionLayoutGroup.horizontal(layoutSize: mainGroupSize, subitems: [bigItem, nestedGroup, nestedGroup, nestedGroup]) let section = NSCollectionLayoutSection(group: mainGroup) let layout = UICollectionViewCompositionalLayout(section: section) return layout } |
- Previously, in NSCollectionLayoutGroups we used only one item with subitems parameter and here we used more than one for some groups.
- Here bigger item take up 40% of the width of their containing group, and the full height while tiny items taking up the remiaing part of the witdth with one third height of their containing group.
- Also add the tiny items in nested groups which positioned items vertically.
- Then in main group positioned horizentally with a big item and nested groups.
2. ) Then add the compositional layout to our collection view as:
1 2 3 4 |
collectionView.delegate = self collectionView.dataSource = self collectionView.collectionViewLayout = createNestedGroupLayout() collectionView.reloadData() |
3.) At last, run it and it displayed as:
Conclusion
If you have any comments, questions, or recommendations, feel free to post them in the comment section below!
For other blogs, please click here.