WaterfallLayout is a UICollectionViewLayout subclass for vertically laying out views like a waterfall, just like Pinterest app.
Deployment target iOS 11.0+
- Xcode > File > Swift Packages > Add Package Dependency
- Add
https://github.com/Jinya/WaterfallLayout.git - Select "Up to Next Minor" from "0.2.0"
Once you've integrated the WaterfallLayout into your project, using it with a collection view is easy.
At the top of the file where you'd like to use WaterfallLayout (likely UIViewController subclass).
import WaterfallLayoutCreate your UICollectionView instance, passing in a WaterfallLayout instance for the layout parameter.
let layout = WaterfallLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)Add collectionView to its superview, then properly constrain it using Auto Layout or manually set its frame property.
view.addSubview(collectionView)
collectionView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
collectionView.topAnchor.constraint(equalTo: view.topAnchor),
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])Register your cell and reusable view types with your collection view.
collectionView.register(MyCustomCell.self, forCellWithReuseIdentifier: "MyCustomCellReuseIdentifier")
// Only necessary if you want section headers
collectionView.register(MyCustomHeader.self, forSupplementaryViewOfKind: UICollectionView.SupplementaryViewKind.sectionHeader, withReuseIdentifier: "MyCustomHeaderReuseIdentifier")
// Only necessary if you want section footers
collectionView.register(MyCustomFooter.self, forSupplementaryViewOfKind: UICollectionView.SupplementaryViewKind.sectionFooter, withReuseIdentifier: "MyCustomFooterReuseIdentifier")Now that you've registered your view types with your collection view, it's time to wire up the data source. Like with any collection view integration, your data source needs to conform to UICollectionViewDataSource. If the same object that owns your collection view is also your data source, you can simply do this:
collectionView.dataSource = selfLastly, it's time to configure the layout to suit your needs. Like with UICollectionViewFlowLayout and UICollectionViewDelegateFlowLayout, WaterfallLayout configured its layout through its UICollectionViewDelegateWaterfallLayout.
To start configuring WaterfallLayout, set your collection view's delegate property to an object conforming to UICollectionViewDelegateWaterfallLayout. If the same object that owns your collection view is also your delegate, you can simply do this:
collectionView.delegate = selfHere's an example delegate implementation:
extension ViewController: UICollectionViewDelegateWaterfallLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, numberOfColumnsInSection section: Int) -> Int {
// You can dynamically configure the number of columns in a section here, e.g., depending on the horizontal size of the collection view.
return traitCollection.horizontalSizeClass == .compact ? 2 : 4
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Here to configure size for every cell.
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .init(top: 10, left: 10, bottom: 10, right: 10)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumColumnSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return .init(width: collectionView.bounds.width, height: 80)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return .init(width: collectionView.bounds.width, height: 80)
}
}If you've followed the steps above, you should have a working UICollectionView using WaterfallLayout! If you'd like to work with a pre-made example, check out the included example project.
WaterfallLayout released under the MIT license. See LICENSE for details.
WaterfallLayout was heavily inspired by CHTCollectionViewWaterfallLayout.
