[Swift] Compositional Layout - 헤더, 다양한 layout적용
Modern Collection View 와 MVVM 패턴 가이드
[iOS] Swift Modern Collection View & MVVM 패턴 가이드 강의 - 인프런
MVVM 패턴과 Modern Collection View를 사용해 네트워킹을 구현하고, 다양하고 동적인 Collection View를 자유자재로 다룰 수 있게 됩니다., Swift iOS UI, 제대로 다루는 핵심 기술! 📲 iOS Swift 레이아웃 구현을
www.inflearn.com
헤더 추가하기
헤더를 추가하기 위해 다음작업들이 필요하다
- 헤더 구현( UICollectionReusableView )
- 헤더 레지스터
- 헤더를 데이터소스에 추가
- 헤더를 레이아웃에 추가
헤더를 레지스터하는 방법은 cell레지스터와 비슷하다
collectionView.register(HeaderView.self, forSupplementaryViewOfKind: AlbumsViewController.sectionHeaderElementKind, withReuseIdentifier: HeaderView.reuseIdentifier)
forSupplementaryViewOfKind : 레이아웃에 사용
withReuseIdentifier: 데이터소스에 사용
이제 헤더를 데이터소스에 추가하려면
dataSource.supplementaryViewProvider = { (collectionView, kind, indexPath) -> UICollectionReusableView? in
return headerViewdataSource.supplementaryViewProvider = { (collectionView, kind, indexPath) -> UICollectionReusableView? in
guard let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: HeaderView.reuseIdentifier, for: indexPath) as? HeaderView else { fatalError()}
//indexPath 통해 섹션 인덱스 접근 가능
return headerView
}
}
이렇게 헤더뷰를 dequeueReusableSupplementaryView 통해 불러와 사용한다.
이제 마지막으로 레이아웃에 추가한다
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: AlbumsViewController.sectionHeaderElementKind, alignment: .top)
이렇게 헤더의 레이아웃을 잡은후
let section = NSCollectionLayoutSection(group: group)
section.boundarySupplementaryItems = [header]
기존 section 레이아웃 boundarySupplementaryItems에 넣어주면 된다.
섹션별로 다른 Cell 다른 레이아웃 섞기
다른 레이아웃을 섞기위해서 다음 과정이 필요하다.
- cell 구현 (UICollectionViewCell)
- 레지스터
- 데이터소스에서 섹션별 분기
- 레이아웃 구현
cell 구현 & 레지스터는 기존 방식과 같다 ( 패스)
데이터소스에서 섹션별로 분기 처리해 섹센별로 다른 cell을 사용할수 있다.
데이터 소스는 이런 구조로 생성된다.
UICollectionViewDiffableDataSource<Section,AlbumItem>(collectionView: <#UICollectionView#>, cellProvider: <#(UICollectionView, IndexPath, AlbumItem) -> UICollectionViewCell?#>)
(Datasource에 관련해는 다음에 알아보기로…)
cellProvider 파라미터 안에 section 별로 셀을 넣어주면 된다.
Datasource 코드
dataSource = UICollectionViewDiffableDataSource
<Section, AlbumItem>(collectionView: albumsCollectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, albumItem: AlbumItem) -> UICollectionViewCell? in
// cellProvider 부분
//섹션을 따로 정의했음, 인덱스로 처리해도 무관
let sectionType = Section.allCases[indexPath.section]
switch sectionType {
///섹션별로 다른 cell 리턴
case .featuredAlbums:
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FeaturedAlbumItemCell.reuseIdentifer, for: indexPath) as? FeaturedAlbumItemCell else {fatalError()}
return cell
default:
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: AlbumItemCell.reuseIdentifer,
for: indexPath) as? AlbumItemCell else { fatalError("Could not create new cell") }
return cell
}
UICollectionViewCompositionalLayout은
이런 구조로 구성된다. 해당 레이아웃이 collectionview 생성시 들어간다.
UICollectionViewCompositionalLayout { <#Int#>, <#NSCollectionLayoutEnvironment#> in
<#code#>
}
위의 Int 파라미터가 섹션의 인덱스를 의미한다. 따라서 섹션별 다른 레이아웃 적용이 가능하다.
func generateFeaturedAlbumsLayout(isWide: Bool) -> NSCollectionLayoutSection
위와같이 레이아웃을 리턴하는 함수 구현후 UICollectionViewCompositionalLayout 생성시에 원하는 섹션에 레이아웃을 넣어주면 된다.