[내일배움캠프 9주차 (03/04)]

yeseul jang·2026년 3월 4일

내일배움캠프

목록 보기
16/32
BeforeAfter

collectionView 으로 다양한 레이아웃 잡기

1) Compositional Layout이란

UICollectionViewCompositionalLayout는 섹션(Section)마다 완전히 다른 레이아웃을 조합(Composition)해서 만들 수 있는 레이아웃 시스템이다.

상단의 예매 화면처럼 섹션마다 UI 형태가 다르게 만들 수 있다.

  • 섹션0: 극장 선택(2x2 그리드)
  • 섹션1: 날짜 선택(가로 스크롤)
  • 섹션2: 시간 선택(3열 그리드)
  • 섹션3: 인원 선택(두꺼운 리스트)
  • 섹션4: 예매하기 버튼(단일 셀)

2) 각 섹션마다 다른 레이아웃을 적용하는 방법

private func makeLayout() -> UICollectionViewLayout {
    UICollectionViewCompositionalLayout { sectionIndex, environment in
        switch sectionIndex {
        case 0: return self.make2x2GirdSection(environment: environment)
        case 1: return self.makeHorizontalScrollSection(environment: environment)
        case 2: return self.make3x2GirdSection(environment: environment)
        case 3: return self.makeListSection(environment: environment)
        default: return self.makeBookingSection(environment: environment)
        }
    }
}
  • sectionIndex로 섹션별 레이아웃을 분기해서 각 섹션에 다른 레이아웃을 준다.
  • environment로 해당 컬렉션뷰의 유효 크기를 얻어서 다양한 사이즈의 화면에 width 계산을 할 수 있다.

3) 다양한 레이아웃 만들기

섹션 0: 2x2 그리드 (극장 선택)

  • 일단 make2x2GirdSection(environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection 이런식으로 environment 받고 NSCollectionLayoutSection을 반환하는 함수를 만든다.
let spacing: CGFloat = 10
    
let containerSize = environment.container.effectiveContentSize
let itemWidthSize = (containerSize.width - spacing * 3) / 2
let itemHeightSize = itemWidthSize / 2
  • environment를 이용해서 실제 화면 크기를 구한 다음에 그걸 기준으로 나누어준다.
  • 간격을 제외하고 실제로 차지할 셀의 크기를 구한다고 보면 된다.
// 아이템 사이즈 지정
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        // 가로 한줄 구성
        let rowGroup = NSCollectionLayoutGroup.horizontal(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .absolute(itemWidthSize * 2),
                heightDimension: .absolute(50)
            ),
            repeatingSubitem: item,
            count: 2
        )
        
        rowGroup.interItemSpacing = .fixed(spacing)
        
        // 2번 쌓기
        let gridGroup = NSCollectionLayoutGroup.vertical(
            layoutSize:NSCollectionLayoutSize(
                widthDimension: .absolute(itemWidthSize * 2),
                heightDimension: .absolute(100)
            ),
            repeatingSubitem: rowGroup,
            count: 2
        )
  • 이제 테트리스 하듯이 쌓으면 된다. 2x2 그리드이기 때문에 한줄에 2개를 2번 쌓는다.
gridGroup.interItemSpacing = .fixed(spacing)
        
        let section = NSCollectionLayoutSection(group: gridGroup)
        section.interGroupSpacing = spacing
        
        section.contentInsets = .init(top: spacing, leading: spacing, bottom: spacing, trailing: spacing)
        section.boundarySupplementaryItems = [makeHeaderItem(height: 60)]
        
        return section
  • 이제 섹션 구성이 끝났으니 간격 설정을 하고 section을 반환한다.

섹션 1: 가로 스크롤 (날짜 선택)

  • 다른 것들은 다 위와 비슷하다.
  • 원하는 아이템(셀)과 그룹을 고정 크기로 잡고, 섹션 자체를 가로로 스크롤하게 만든다.
    section.orthogonalScrollingBehavior = .continuous
  • 스크롤 설정을 잊으면 안된다!

섹션 2: 3x2 그리드 (시간 선택)

let containerSize = environment.container.effectiveContentSize
let itemWidthSize = (containerSize.width - spacing * 4) / 3
  • 한줄에 3개씩 들어가도록 itemWidth를 계산해준다.

섹션 3: 두꺼운 리스트 (인원 선택)

 let containerSize = environment.container.effectiveContentSize
 let itemWidthSize = (containerSize.width - spacing * 2)
  • 가로는 꽉 차게, 높이는 직접지정해서 90짜리 셀을 2개 세로로 쌓음.

섹션 3: 두꺼운 리스트 (인원 선택)

  • 위와 레이아웃은 동일한데 셀을 다르게 하고 싶어서 만들었다. 근데 TIL 쓰며 생각해보니까 위의 레이아웃을 같이 사용해도 될듯하다 어차피 넣어줄 자료구조로 결정되는거라서 😅😅🤯
profile
iOS 개발

0개의 댓글