[iOS] UICollectionViewCompositionalLayout

홍승현·2022년 11월 23일
0

CollectionView

목록 보기
3/3
post-thumbnail

글 작성 기준
Xcode: Version 14.1 (14B47b)
iOS: 16.0^
Swift: 5.7.1 (5.7.1.135.3)

CompositionalLayout

  • CollectionViewLayout의 유형 중 하나로, 여러 복잡한 레이아웃을 보다 적은 양의 코드로 보다 정교하게 구현할 수 있도록 만든 layout

  • Section - Group - Item 순의 개념이 존재하며, 각 Section 별로 뷰의 배치를 다양하게 활용할 수 있다.

개념 알아보기

NSCollectionLayoutItem


해당 layout의 근본 컴포넌트이며 개별 컨텐츠의 크기, 간격, 정렬에 대한 설계도(blueprint)를 나타낸다. 일반적으로 Item은 Cell이 되지만 Header, Footer, Decoration와 같은 SupplementaryView도 될 수 있다.
ItemGroup과 결합(Combine)하여 각 항목이 서로 관련되어 정렬되는 방식을 결정한다. NSCollectionLayoutSize로 사이즈를 설정한다.

NSCollectionLayoutGroup

Item을 담는 Container 역할. 각 Item을 가로 열, 세로 열 등 어떻게 배치할 지 결정한다. Group은 단지 배치에 대한 정의를 내려주는 객체일 뿐, 렌더링 하지는 않는다.
NSCollectionLayoutSize로 사이즈를 설정한다.

NSCollectionLayoutSection


Group을 담는 Container 역할을 하며, Section을 만드는 데 사용되는 Group의 속성에 따라 결정된다.
Section은 고유 배경, header, footer를 가질 수 있다.

시작해보기

Note: 앞서 CompositionalLayout은 세 가지 크기 조절 옵션을 제공한다.

  1. absolute
    • 고정값으로 item의 너비와 높이를 설정한다.
  2. estimated
    • 추정치 값으로 item의 너비와 높이를 설정한다. item의 컨텐츠 크기에 따라 달라진다.
  3. fractionalWidth
    • SuperView의 너비를 기준으로 비율로써 크기를 설정한다.
  4. fractionalHeight
    • SuperView의 높이를 기준으로 비율로써 크기를 설정한다.

1. Item layout 생성

  • Item은 NSCollectionLayoutItem 타입이며, 위에 언급한 크기 옵션을 맞춰 제공해주어야한다.
convenience init(layoutSize: NSCollectionLayoutSize)
  • Item을 1:1비율의 사이즈로 보여주기 위해 다음의 코드를 작성한다.
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
                                      heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
  • 각 Item 별 간격을 주기 위해 Inset 값을 설정한다.
item.contentInsets = NSDirectionalEdgeInsets(top: 1, leading: 1, bottom: 1, trailing: 1)

2. Group layout 생성

  • 수평 또는 수직 축을 기준으로 Item을 처리하는 메서드가 존재한다.
// horizontal
class func horizontal(layoutSize: NSCollectionLayoutSize, repeatingSubitem subitem: NSCollectionLayoutItem, count: Int) -> Self

// vertical
class func vertical(layoutSize: NSCollectionLayoutSize, repeatingSubitem subitem: NSCollectionLayoutItem, count: Int) -> Self
  • 3x4만큼의 셀을 보여주기 위해 다음과 같이 설정한다.
let group = NSCollectionLayoutGroup.horizontal(
  layoutSize: .init(widthDimension: .fractionalWidth(1/4),
                    heightDimension: .fractionalHeight(1/3)),
  repeatingSubitem: item,
  count: 4
)

3. Section layout 생성

  • 앞서 만들었던 group을 주입한다.
let section = NSCollectionLayoutSection(group: group)

4. UICollectionViewCompositionalLayout 생성 및 설정

  • UICollectionViewCompositionalLayout(section:)을 사용하여 앞선 section을 주입하여 layout을 생성한다.
let layout = UICollectionViewCompositionalLayout(section: section)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)

활용해보기

1. 인스타그램 스토리

1-1. item, group 설정

// item
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
                                      heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
  
// group
let group = NSCollectionLayoutGroup.horizontal(
  layoutSize: .init(widthDimension: .absolute(70),
                    heightDimension: .absolute(70)),
  subitems: [item]
)
  • 위 코드 결과화면

1-2. section 설정

  • section에서는 orthogonalScrollingBehavior 프로퍼티를 이용하여 수평스크롤을 설정할 수 있다.
  • Group별 spacing을 설정할 수 있다.
// section
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.interGroupSpacing = 10
section.contentInsets = .init(top: 0, leading: 10, bottom: 30, trailing: 10)
section.boundarySupplementaryItems = [
  .init(layoutSize: .init(widthDimension: .fractionalWidth(1),
                          heightDimension: .estimated(50)),
        elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
]

1-3 Cell style 설정

  • 둥근 모양을 생성한다.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  // codes...
  cell.backgroundColor = .systemGray5
  cell.layer.cornerRadius = cell.frame.height / 2
  cell.configure(with: String(indexPath.item)) // Custom Function
  return cell
}

결과물

profile
블로그 이전: https://www.whitehyun.com

0개의 댓글