Modern Collection View [5] - Compositional Layout | Per Section Composable Layout
let sectionIdentifier = self.dataSource.snapshot().sectionIdentifiers[sectionIndex]
case .storiesCarousel:
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(1)))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .absolute(70), heightDimension: .estimated(1)), subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 16
section.contentInsets = .init(top: 0, leading: 16, bottom: 16, trailing: 16)
section.orthogonalScrollingBehavior = .continuous
section.supplementariesFollowContentInsets = false
section.boundarySupplementaryItems = [self.supplementaryHeaderItem(), self.supplementarySeparatorFooterItem()]
return section
NSCollectionLayoutGroup.horizontal
을 통해 수직이 아닌 수평 방향으로 이어지는 컬렉션 뷰 방향continuous
는 셀 중간이 잘려도 연속적으로 이어지는 페이징 기법case .bannerCarousel:
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(1)))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(0.77), heightDimension: .estimated(1)), subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 16
section.supplementariesFollowContentInsets = false
section.contentInsets = .init(top: 0, leading: 16, bottom: 16, trailing: 16)
section.boundarySupplementaryItems = [self.supplementaryHeaderItem(), self.supplementarySeparatorFooterItem()]
section.orthogonalScrollingBehavior = .continuous
return section
case .columnCarousel:
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: itemSize, subitems: [item])
let containerGroup = NSCollectionLayoutGroup.vertical(layoutSize: .init(widthDimension: .fractionalWidth(0.8), heightDimension: .estimated(1)), subitems: Array(repeating: group, count: 3))
let section = NSCollectionLayoutSection(group: containerGroup)
section.contentInsets = .init(top: 0, leading: 16, bottom: 16, trailing: 16)
section.interGroupSpacing = 16
section.supplementariesFollowContentInsets = false
section.boundarySupplementaryItems = [self.supplementaryHeaderItem(), self.supplementarySeparatorFooterItem()]
section.orthogonalScrollingBehavior = .groupPaging
return section
NSCollectionLayoutGroup
이 핵심.groupPaging
기법은 .continuous
처럼 셀이 잘려도 이어지는 게 아니라 셀 단위로 넘길 수 있음case .list:
var listConfiguration = UICollectionLayoutListConfiguration(appearance: .grouped)
listConfiguration.headerMode = .supplementary
listConfiguration.footerMode = .supplementary
return NSCollectionLayoutSection.list(using: listConfiguration, layoutEnvironment: layoutEnvironment)
case .grid:
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(1)))
guard let orientation = UIApplication.shared.windows.first(where: { $0.isKeyWindow})?.windowScene?.interfaceOrientation else { return nil }
let noOfColumns: Int
switch orientation {
case .landscapeLeft, .landscapeRight :
noOfColumns = 8
default: noOfColumns = 4
}
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(1)), subitem: item, count: noOfColumns)
group.interItemSpacing = .fixed(16)
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 16
section.contentInsets = .init(top: 0, leading: 16, bottom: 16, trailing: 16)
section.boundarySupplementaryItems = [self.supplementaryHeaderItem(), self.supplementarySeparatorFooterItem()]
return section
iPhone 14
)에서는 traitCollection
의 프로퍼티를 통해 가로/세로 모드를 확인하는 게 정확하지 않았기 때문에 UIWindow를 통해 직접적으로 확인let noOfColumns = layoutEnvironment.traitCollection.horizontalSizeClass == .compact ? 4 : 8
iPhone 12
에서는 정상적으로 작동하는 것을 확인했지만, 일단 모든 시뮬레이터 환경에서 동작하는 UIWindow를 통한 코드를 선택'단 하나'의 컬렉션 뷰를 통해 위와 같은 뷰를 그릴 수 있다는 건 컴포지녀설 레이아웃이 가진 어마어마한 힘을 단적으로 보여준다고 해도 과언이 아니다! 여러 개의 컬렉션 뷰를 사용한다면 특정 구성이 바뀔 때마다 구성을 바꿔야 하고, 별도의 뷰를 로드해야 하는 등 불필요한 리소스 사용이 불가피할 것이기 때문이다!