I want to build the following layout using UIKit
.
Currently I'm using an UICollectionView
in combination with a Composotional Layout
. The following code produces this result:
Relevant Method:
private static func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
let headerItem = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(35)
)
)
let horizontalGroupItem = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(0.95),
heightDimension: .fractionalHeight(1.0)
)
)
let horizontalMainGroup = NSCollectionLayoutGroup.horizontal(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(100)
),
subitems: [horizontalGroupItem]
)
horizontalMainGroup.interItemSpacing = .fixed(10)
let group = NSCollectionLayoutGroup.vertical(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(135)
),
subitems: [headerItem, horizontalMainGroup])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 10
section.orthogonalScrollingBehavior = .continuous
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
So the main problem is, that the top element doesn't take up the full width of the section. Instead it's limited to the width of group
. Does anyone know how to get the desired result? :-)
Full Example:
import UIKit
class ViewController: UIViewController {
private let colors: [UIColor] = [.systemTeal, .systemBlue, .systemGray, .systemOrange]
private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: ViewController.createCompositionalLayout())
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
collectionView.backgroundColor = .systemBackground
collectionView.frame = view.bounds
collectionView.dataSource = self
collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.reuseID)
}
private static func createCompositionalLayout() -> UICollectionViewCompositionalLayout {
let headerItem = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(35)
)
)
let horizontalGroupItem = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(0.95),
heightDimension: .fractionalHeight(1.0)
)
)
let horizontalMainGroup = NSCollectionLayoutGroup.horizontal(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(100)
),
subitems: [horizontalGroupItem]
)
horizontalMainGroup.interItemSpacing = .fixed(10)
let group = NSCollectionLayoutGroup.vertical(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(135)
),
subitems: [headerItem, horizontalMainGroup])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 10
section.orthogonalScrollingBehavior = .continuous
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
}
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.reuseID, for: indexPath) as? MyCollectionViewCell
cell?.backgroundColor = colors[indexPath.item]
cell?.label.text = "\(indexPath.item)"
return cell ?? UICollectionViewCell()
}
}
//MARK: - CollectionViewCell
class MyCollectionViewCell: UICollectionViewCell {
static let reuseID = "myCell"
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
label.frame = contentView.bounds
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}