Swift: Waterfall CollectionView Layout (2021, Xcode 12, Swift 5) - iOS Development
CHTCollectionViewWaterfallLayout
라이브러리 사용 private let collectionView: UICollectionView = {
let layout = CHTCollectionViewWaterfallLayout()
layout.itemRenderDirection = .leftToRight
layout.columnCount = 2
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: CustomCollectionViewCell.identifier)
return collectionView
}()
CHTCollectionViewWaterfallLayout
레이아웃을 파라미터로 넘겨주면 이후 델리게이트 함수를 사용 가능extension CollectionViewController: CHTCollectionViewDelegateWaterfallLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.size.width / 2, height: models[indexPath.row].height)
}
}
import UIKit
import CHTCollectionViewWaterfallLayout
class CollectionViewController: UIViewController {
private let collectionView: UICollectionView = {
let layout = CHTCollectionViewWaterfallLayout()
layout.itemRenderDirection = .leftToRight
layout.columnCount = 2
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: CustomCollectionViewCell.identifier)
return collectionView
}()
private var models = [ImageModel]()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.frame = view.bounds
}
private func setUI() {
view.backgroundColor = .systemBackground
view.addSubview(collectionView)
collectionView.dataSource = self
collectionView.delegate = self
for _ in 0..<100 {
let number = Int.random(in: 1...15)
let height = CGFloat.random(in: 200...400)
let name = "sf_\(number)"
let model = ImageModel(imageName: name, height: height)
models.append(model)
}
}
}
extension CollectionViewController: UICollectionViewDelegate {
}
extension CollectionViewController: CHTCollectionViewDelegateWaterfallLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.size.width / 2, height: models[indexPath.row].height)
}
}
extension CollectionViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CustomCollectionViewCell.identifier, for: indexPath) as? CustomCollectionViewCell else {
return CustomCollectionViewCell()
}
cell.configure(with: models[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return models.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
}
import UIKit
class CustomCollectionViewCell: UICollectionViewCell {
static let identifier = "CustomCollectionViewCell"
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView)
contentView.clipsToBounds = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
imageView.frame = contentView.bounds
}
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
}
func configure(with model: ImageModel) {
if let image = UIImage(named: model.imageName) {
imageView.image = image
}
}
}
import Foundation
struct ImageModel {
let imageName: String
let height: CGFloat
}