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 WaterfallLayout
Create 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 = self
Lastly, 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 = self
Here'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
.