Skip to content

edonv/CompositionalLayoutBuilder

Repository files navigation

CompositionalLayoutBuilder

CompositionalLayoutBuilder gives you the ability to "compose" a UICollectionViewCompositionalLayout/NSCollectionViewCompositionalLayout via result builders syntax.

It can be used in any context you might use a UICollectionView/NSCollectionView, including another package of mine: CollectionView (which will come pre-packaged with initializers that use the layout builders).

Install

To add CompositionalLayoutBuilder to an Xcode project, go to File > Add Package Dependencies..., and paste https://github.com/edonv/CompositionalLayoutBuilder into the Search field.

To add it manually to a Swift Package, add the following to the dependencies property in the Package.swift file:

.package(
    url: "https://github.com/edonv/CompositionalLayoutBuilder",
    upToNextMajor(from: "0.0.0")
)

Comparison

With CompositionalLayoutBuilder:

let layout: CompositionalLayout = {
    CompositionalLayout {
        CompositionalSection {
            CompositionalGroup(.horizontal, width: .fractionalWidth(1), height: .absolute(200)) {
                LayoutGroup(.vertical, width: .fractionalWidth(0.75), height: .fractionalHeight(1)) {
                    LayoutItem(width: .fractionalWidth(1), height: .fractionalHeight(0.5))
                        .repeating(count: 2)
                }
                .interItemSpacing(.fixed(8))
                
                CompositionalItem(width: .fractionalWidth(0.25), height: .fractionalHeight(1))
            }
            .interItemSpacing(.fixed(16))
        }

        CompositionalSection {
            CompositionalGroup(.horizontal, width: .fractionalWidth(1), height: .absolute(100)) {
                CompositionalItem(width: .fractionalWidth(0.5), height: .fractionalHeight(1))
            }
        }
        .orthogonalScrollingBehavior(.continuous)
    }
    .scrollDirection(.vertical)
}()

With vanilla UICollectionViewCompositionalLayout:

let layout: UICollectionViewCompositionalLayout = {
    UICollectionViewCompositionalLayout { section, _ in
        switch section {
        case 0:
            let innerItem = NSCollectionLayoutItem(layoutSize: .init(
                widthDimension: .fractionalWidth(1),
                heightDimension: .fractionalHeight(0.5)
            ))
            
            let innerGroup = NSCollectionLayoutGroup.vertical(
                layoutSize: .init(
                    widthDimension: .fractionalWidth(0.75),
                    heightDimension: .fractionalHeight(1)
                ),
                subitem: innerItem,
                count: 2
            )
            
            innerGroup.interItemSpacing = .fixed(8)
            
            let outerItem = NSCollectionLayoutItem(layoutSize: .init(
                widthDimension: .fractionalWidth(0.25),
                heightDimension: .fractionalHeight(1)
            ))
            
            let mainGroup = NSCollectionLayoutGroup.horizontal(
                layoutSize: .init(
                    widthDimension: .fractionalWidth(1),
                    heightDimension: .absolute(200)
                ),
                subitems: [innerGroup, outerItem]
            )
            
            return .init(group: mainGroup)
            
        case 1:
            let innerItem = NSCollectionLayoutItem(layoutSize: .init(
                widthDimension: .fractionalWidth(0.5),
                heightDimension: .fractionalHeight(1)
            ))
            
            let mainGroup = NSCollectionLayoutGroup.horizontal(
                layoutSize: .init(
                    widthDimension: .fractionalWidth(1),
                    heightDimension: .absolute(100)
                ),
                subitems: [innerItem]
            )
            
            let section = NSCollectionLayoutSection(group: mainGroup)
            section.orthogonalScrollingBehavior = .continuous
            return section
            
        default:
            return nil
        }
    }
}()

Documentation

Documentation can be found here, hosted on Swift Package Index.

To-Do's

  • Add equivalent UIKit code to README for comparison.