環境
swift version5.4
コード
下準備
import UIKit
extension UIView {
/// クラス名を文字列で返す
static var className: String { String(describing: Self.self) }
}
import UIKit
extension UICollectionView {
func register<T: UICollectionViewCell>(type: T.Type) {
let nib = UINib(nibName: T.className, bundle: nil)
register(nib, forCellWithReuseIdentifier: T.className)
}
func dequeueReusableCell<T: UICollectionViewCell>(withReuseCell type: T.Type, for indexPath: IndexPath) -> T {
let cell = dequeueReusableCell(withReuseIdentifier: T.className, for: indexPath) as! T
return cell
}
}
import UIKit
/// UICollectionViewのカラムレイアウトを作成するためのstruct
struct ColumnSetting {
let column: CGFloat
let verticalMargin: CGFloat
let sideMargin: CGFloat
let interMargin: CGFloat
let aspectRatio: CGFloat
/// 指定のカラム数のレイアウトを作成するための設定
/// - Parameters:
/// - column: カラム数
/// - verticalMargin: 上下の余白。初期値0。
/// - outerMargin: 左右の余白。初期値0。
/// - interMargin セル間の余白。初期値0。
/// - aspectRatio: 横を1としたときの縦の比率。初期値1。
init(column: Int, verticalMargin: CGFloat = 0,
sideMargin: CGFloat = 0, interMargin: CGFloat = 0, aspectRatio: CGFloat = 1) {
self.column = CGFloat(column)
self.verticalMargin = verticalMargin
self.sideMargin = sideMargin
self.interMargin = interMargin
self.aspectRatio = aspectRatio
}
/// UICollectionViewインスタンスのcollectionViewLayoutプロパティに代入する
func collectionViewLayout() -> UICollectionViewFlowLayout {
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: verticalMargin, left: sideMargin,
bottom: verticalMargin, right: sideMargin)
layout.minimumInteritemSpacing = interMargin
return layout
}
/// UICollectionViewDelegateFlowLayoutのsizeForItemAtメソッドの返却値として設定する
func sizeForItem(parent: UICollectionView) -> CGSize {
let totalSideMargin: CGFloat = sideMargin * 2
let intervalCount: CGFloat = column - 1
let totalInterMargin = interMargin * intervalCount
let totalMargin = totalSideMargin + totalInterMargin
let availableWidth = parent.frame.width - totalMargin
let baseCellSize = floor(availableWidth / column)
return CGSize(width: baseCellSize, height: baseCellSize * aspectRatio)
}
}
呼び出し
import UIKit
final class SampleViewController: UIViewController {
typealias Cell = SampleCollectionViewCell
private let columnSetting = ColumnSetting(column: 3, sideMargin: 4, interMargin: 4)
@IBOutlet private weak var collectionView: UICollectionView! {
didSet {
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(cell: Cell.self)
collectionView.collectionViewLayout = columnSetting.collectionViewLayout()
}
}
}
// MARK: - UICollectionViewDelegate
extension SampleViewController: UICollectionViewDelegate {
}
// MARK: - UICollectionViewDelegateFlowLayout
extension MatchingViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return columnSetting.sizeForItem(parent: collectionView)
}
}
// MARK: - UICollectionViewDataSource
extension SampleViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return 0
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseCell: Cell.self, for: indexPath)
return cell
}
}
参考
UICollectionViewの列数と行数を端末サイズ関係なく実装する
【Swift】sectionHeadersPinToVisibleBoundsを設定するとスクロールがカクつく不具合修正