UICollectionViewCompositionalLayout
で全てのCellの高さを合わせる方法 uniformAcrossSiblings
uniformAcrossSiblingsを紹介します。
What’s new in UIKitで紹介されていたものです。
NSCollectionLayoutSize
の高さをestimated
にすると、Cellの高さに応じてitemやgroupの高さが変化します。しかし、group内の高さは以下のようにバラバラになってしまいます。このようなケースでは、uniformAcrossSiblings(estimate:)
で簡単に統一できます。uniformAcrossSiblings(estimate:)
によって、group内で最大のitem高さに合わせて、他のitemの高さが変化します。
サンプルを貼ります。
import UIKit
import SwiftUI
class UniformSiblingsViewController: UIViewController {
let layout: UICollectionViewCompositionalLayout = {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0/3.0), heightDimension: .uniformAcrossSiblings(estimate: 80.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(80.0))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, repeatingSubitem: item, count: 3)
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}()
lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.layout)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.delegate = self
return collectionView
}()
var diffableDataSource: UICollectionViewDiffableDataSource<Section, Item>!
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.collectionView)
NSLayoutConstraint.activate([
self.collectionView.topAnchor.constraint(equalTo: self.view.topAnchor),
self.collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
self.collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
self.collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
])
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewCell, Item>{ cell, indexPath, item in
cell.contentConfiguration = UIHostingConfiguration(content: {
VStack(spacing: 8){
Text(item.title)
Text(item.body)
}
})
.background(item.background)
}
self.diffableDataSource = UICollectionViewDiffableDataSource(collectionView: self.collectionView, cellProvider: { collectionView, indexPath, item in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
})
var snapShot = NSDiffableDataSourceSnapshot<Section, Item>()
snapShot.appendSections([.main])
snapShot.appendItems([
Item(title: "hello, world", body: "hoge\nfoo\nbar", background: Color.red),
Item(title: "hello\nworld", body: "hoge", background: Color.green),
Item(title: "hello", body: "hoge", background: Color.blue),
])
self.diffableDataSource.apply(snapShot, animatingDifferences: false)
}
}
extension UniformSiblingsViewController {
enum Section {
case main
}
struct Item: Hashable {
let title: String
let body: String
let background: Color
}
}
layout
の定義を見てください。group
をestimated
に、item
の高さを
uniformAcrossSiblings(estimate:)
にしているのがポイントです。
let layout: UICollectionViewCompositionalLayout = {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0/3.0), heightDimension: .uniformAcrossSiblings(estimate: 80.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(80.0))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, repeatingSubitem: item, count: 3)
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}()