UICollectionView(frame: .zero, collectionViewLayout: $$$$$$$)
collectionviewLayout 부분에 UICollectionViewCompositionalLayout()을 넣어주면 된다
보통 Helper를 이용해서 만들어준뒤에 넣어준다
Compositional Layout을 만들때는 3가지가 필요하다
private func makeLayout() -> UICollectionViewCompositionalLayout {
UICollectionViewCompositionalLayout { [ weak self ]sectionIndex, layoutEnviro in
guard let self else { return nil}
let section = self.sections[sectionIndex]
switch section {
case .first:
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
item.contentInsets = .init(top: 1, leading: 5, bottom: 1, trailing: 5)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .absolute(70), heightDimension: .absolute(70)), subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.interGroupSpacing = 10
section.boundarySupplementaryItems = [supplementaryHeaderItem()]
return section
case .second:
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1)))
item.contentInsets = .init(top: 3, leading: 3, bottom: 3, trailing: 3)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(50)), repeatingSubitem: item, count: 4)
let section = NSCollectionLayoutSection(group: group)
section.boundarySupplementaryItems = [supplementaryHeaderItem()]
return section
case .third:
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
item.contentInsets = .init(top: 10, leading: 10, bottom: 10, trailing: 10)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(0.4)), repeatingSubitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
section.boundarySupplementaryItems = [supplementaryHeaderItem()]
section.orthogonalScrollingBehavior = .groupPaging
return section
}
}
}
헤더나 푸터를 만들때 이런식으로 레지스터 해서 사용을 해주고
dataSource?.supplementaryViewProvider = { (collectionView, kind, indexPath) in
guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: Header.identifier, for: indexPath) as? Header else {
fatalError("Could not dequeue sectionHeader: \(Header.identifier)")
}
return sectionHeader
}
configureDataSource를 할때 넣어준다
private func supplementaryHeaderItem() -> NSCollectionLayoutBoundarySupplementaryItem {
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(20)), elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
// header.pinToVisibleBounds = true
return header
}
let config = UICollectionViewCompositionalLayoutConfiguration()
layout.configuration = config
// config에서 줄수있는 세팅은 다음과 같다
1. 전체 섹션의 스크롤 방향(각 섹션마다 스크롤방향을 다르게 쓰고싶다면 각 섹션에 들어가서 수정해줘야 한다)
config.scrollDirection = .horizontal
2. 각섹션각의 스페이싱
config.interSectionSpacing = 20
3. 헤더와 풋터를 전체 섹션에 다 넣어줄수도 있따
ompositional Layout을 대충만들었는데 정확하게 만드는 방법은 이렇다
// 우선 사이즈를 정해준다
let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(150))
// 헤더를 만들어주는데 첫번째 인자에서 사이즈를 넣어주고, 두번째는 뭔지 모름, 세번째는 얼라인먼트? bottom에다가 넣으면 bottom으로 들어갈까?
마지막은 offset. 보통은 y축만 수정하게 된다
let layoutHeader1 = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: "Header1", alignment: .top, absoluteOffset: CGPoint(x: 0, y: -60))
위에서 적은거처럼 diffableDataSource를 쓸경우에는 diffableDataSource안에서 supplementary provider에서 리턴해주도록 한다
compositional Layout 자료
https://medium.com/@hdmdhr/pin-header-to-the-top-in-a-multi-sections-uicollectionview-9f1103f247a5
***Section에 BackgroundView 넣는법*
layout.register(BackgroundReusableView.self,
forDecorationViewOfKind: BackgroundReusableView.identifier)
// 섹션 layout으로 가서 이니셜라이징 해줌
let backgroundItem = NSCollectionLayoutDecorationItem.background(elementKind: BackgroundReusableView.identifier)
// 컨텐트 인셋도 똑같이 줌
backgroundItem.contentInsets = section.contentInsets
// 섹션레이아웃에 추가해줌
section.decorationItems = [backgroundItem]
compositional을 쓸때는 레이아웃에 헤더를 만들어주어야한다 이녀석은 단지 레이아웃을 어떻게 그릴지만 정해준다
그리고 diffable DataSource를 쓸때는 DataSource 에 어떤 섹션에서 어떤게 불릴지를 불러주고
그냥쓴다면 여기에 넣어준다
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: CommentHeaderView.identifier, for: indexPath)
return view
}