이제 실제로 CompositionalLayout을 적용하려고 하는데 그전에 아주 간단하게 CompositionalLayout이 무엇인가 왜, 언제 사용하는 것인가 설명하고자 합니다.
CompositionalLayout이란 CollectionView의 여러 layout 방식 중 하나입니다.
구성으로는 item, group, section이라는 구역으로 총 3가지 종류로 나눠져 있어 기본적으로 각각의 size(layout), property를 설정하여 사용합니다.
// Compositional Layout 설정
func createBasicListLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(44))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
각 요소들의 사이즈를 설정하는 방법
- fractionalWidth & fractionalHeight - 컨테이너와의 너비&높이 비율
- absolute - 포인트값으로 지정
- estimated - 후에 content의 크기가 바뀌어 크기가 정확하지 않을 때는 estimate 사용
여기까지는 어렵지 않았다…. 아니 사실 어려웠지만 이 뒤에 layout이나 여러 가지 section에 대한 설정을 해줘야 할때 너무 힘들었…
개발 접을 뻔 했네 진짜로
아무튼 위 코드는 하나의 section에 대한 layout을 설정하는 코드입니다.
제가 이번 프로젝트에서 CollectionView에 Compostional Layout을 사용한 이유는 이전에 아래와 같이 총 3개의 섹션을 포함하고 1번과 2번은 수평 스크롤 3번은 수직 스크롤이 되는 CollectionView를 만들기 위해 복잡한 레이아웃을 배치하는데 Compostional Layout이 제일 적합하다고 생각했기 때문입니다.
저는 UICollectionView에 총 3개(channel, keyword, video)의 section을 만들겁니다.
위의 함수 createBasicListLayout을 내가 만들고자 하는 section layout으로 커스텀하고 모두 호출하여 UICollectionView에 적용한다 라고 생각하면 됩니다.
// channel섹션 layout 설정
private func getChannelSection() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(0.19),
heightDimension: .fractionalHeight(0.17)
)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
return section
}
// HomeSection은 enum
private var homeSource: [HomeSection] = [
HomeSection.channel,
HomeSection.keyword,
HomeSection.video
]
// CollectionView 생성
private lazy var homeCollectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.getLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
//
private func getLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { sectionIndex, env -> NSCollectionLayoutSection? in
switch self.homeSource[sectionIndex] {
case .channel:
return self.getChannelSection()
case .keyword:
return self.getKeywordSection()
case .video:
return self.getVideoSection()
}
}
}
여기서 getLayout은 UICollectionViewDataSource 프로토콜을 채택하면 numberOfSections이라는 현재 section의 수를 반환하는 함수를 선언하게 되는데 이 값만큼 getLayout 함수가 호출됩니다!!
정확히 말하자면 getLayout안에 UICollectionViewCompositionalLayout 클로저가 section의 갯수만큼 호출됩니다… 이거 몰라서 진짜 고생했어요..ㅠㅠ
extension HomeViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return homeSource.count
}
}
정말 섹션의 갯수만큼 불러지는지 테스트 해봤습니다
이제 UICollectionVIewCell을 만들고 목업 아이템(테스트를 위한 기본적인 뷰)를 입히게 되면
아래와 같은 3개의 섹션으로 나뉘어진 결과 이미지를 확인할 수 있습니다
'iOS' 카테고리의 다른 글
[iOS] 콜렉션뷰 Youtube API 활용 #1 (2) | 2024.06.03 |
---|---|
[iOS] CompositionalLayout을 한번 사용해보자 #3 (0) | 2024.05.29 |
[iOS] CompositionalLayout을 한번 사용해보자 #1 (0) | 2024.05.13 |
[iOS] Concurrency(async & await) (0) | 2024.03.31 |
[iOS] 새싹 프로젝트 (BoxOffice STEP3) #2 CollectionView 구현 (0) | 2024.03.24 |