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
}
NSCollectionLayoutDimension
타입의 값을 가진다.let absoluteSize = NSCollectionLayoutSize(widthDimension: .absolute(44),
heightDimension: .absolute(44))
let estimatedSize = NSCollectionLayoutSize(widthDimension: .estimated(200),
heightDimension: .estimated(100))
let fractionalSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.2),
heightDimension: .fractionalWidth(0.2))
// Item width: To lay out 3 items horizontally, use 1/3 of the width of the group.
// Item height: To achieve a consistent height for the items, use `uniformAcrossSiblings(estimate:)`.
let itemCount = 3
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0 / CGFloat(itemCount)),
heightDimension: .uniformAcrossSiblings(estimate: 50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// Group width: To use the entire horizontal width of the section, use the full fractional width.
// Group height: To allow the group's height to grow for the items, use `estimated(_:)`.
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(50))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
repeatingSubitem: item,
count: itemCount)
let section = NSCollectionLayoutSection(group: group)
func setupLayout(){
//너비는 가능한 너비 전체로 채우고자 하면 비율적으로 1
let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(200))
//아이템 크기 설정
let item = NSCollectionLayoutItem(layoutSize: size)
//그룹 설정
let group = NSCollectionLayoutGroup.vertical(layoutSize: size, subitems: [item])
//섹션 그룹 설정
let section = NSCollectionLayoutSection(group: group)
//inset 설정
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20)
section.interGroupSpacing = 20
let layout = UICollectionViewCompositionalLayout(section: section)
detailCollectionView.collectionViewLayout = layout
}
func createPerSectionLayout() -> UICollectionViewLayout {
//sectionIndex로 몇번째 섹션인지 확인 가능
// layoutEnvironment에 레리아웃과 관련된 속성들이 저장되어있음.
let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,
layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
//sectionIndex로 분기하여 적절히 설정
let columns = sectionIndex == 0 ? 2 : 4
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,
subitem: item,
count: columns)
let section = NSCollectionLayoutSection(group: group)
return section
}
return layout
}
func setupLayout(){
let layout = UICollectionViewCompositionalLayout { sectionIndex, environment in
switch sectionIndex{
case 1:
//한 줄에 두 셀을 표시하고자 하므로 0.5
var size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .estimated(130))
//아이템 크기 설정
let item = NSCollectionLayoutItem(layoutSize: size)
//그룹은 섹션 너비 전체를 채우도록
size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(130))
//그룹 설정. 나란히 배치하고자 하므로 horizontal
let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitems: [item])
//그룹 내 inset 설정
//.fixed = 고정값 지정, .flexible = 최소 여백 지정. 현재 상황에서는 비율로 너비가 지정되므로 오차발생 가능성이 있기 때문에 flexible이 바람직함.
group.interItemSpacing = .flexible(20)
//섹션 그룹 설정
let section = NSCollectionLayoutSection(group: group)
//inset 설정
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20)
section.interGroupSpacing = 20
return section
default:
//너비는 가능한 너비 전체로 채우고자 하면 비율적으로 1
let size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(200))
//아이템 크기 설정
let item = NSCollectionLayoutItem(layoutSize: size)
//그룹 설정
let group = NSCollectionLayoutGroup.vertical(layoutSize: size, subitems: [item])
//섹션 그룹 설정
let section = NSCollectionLayoutSection(group: group)
//inset 설정
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20)
section.interGroupSpacing = 20
return section
}
}
detailCollectionView.collectionViewLayout = layout
}
그러나, 두번째 섹션에서 셀을 한 줄에 두개씩 표시하다가 만약 홀수개일 경우에는 빈 부분이 발생한다. 이처럼 마지막 셀은 너비 전체를 채우도록 하고싶을 경우에는 그룹 안에 그룹을 넣어 별도로 설정해주어야 한다.
- 첫번째 라인처럼 두개를 절반으로 배치하는 그룹을 만든다. -> 한 줄에 2개
- 너비 전체를 채우는 아이템을 만든다. -> 한 줄에 1개
- 그룹과 아이템을 다시 그룹으로 묶는다.
...
case 1:
//한 줄에 두 셀을 표시하고자 하므로 0.5
var size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .estimated(130))
//아이템 크기 설정
var item = NSCollectionLayoutItem(layoutSize: size)
//그룹은 섹션 너비 전체를 채우도록
size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(130))
//그룹 설정. 나란히 배치하고자 하므로 horizontal
//첫번째 2개 셀 그룹
var group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitems: [item])
//그룹 내 inset 설정
//.fixed = 고정값 지정, .flexible = 최소 여백 지정. 현재 상황에서는 비율로 너비가 지정되므로 오차발생 가능성이 있기 때문에 flexible이 바람직함.
group.interItemSpacing = .flexible(20)
//섹션 그룹 설정
//두번째 1개 셀 그룹
size = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(130))
item = NSCollectionLayoutItem(layoutSize: size)
group = NSCollectionLayoutGroup.vertical(layoutSize: size, subitems: [group, item])
//위 아래 inset 추가
group.interItemSpacing = .flexible(20)
let section = NSCollectionLayoutSection(group: group)
//inset 설정
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20)
section.interGroupSpacing = 20
return section
...
다만, 이렇게 할 경우 그룹 내의 그룹과 아이템이 겹쳐지는 현상이 발생한다.
이는 첫번째 그룹에서는 horizontal로, 그리고 해당 그룹과 아이템을 묶은 최종 그룹에서는 vertical로 배치했기 때문에 스크롤의 범위는 무한대가 되고, 셀의 높이를 self-sizing으로 했기 때문에 이 상황에서 여백을 .flexible
로 추가하게 되면 배치가 무너진다.
해결법은 .fixed
로 바꾸면 된다.
종종 이렇게 배치가 무너지면 일단 .fixed
로 바꿔보자.