개발/Swift

[Swift] Compositional Layout - 레이아웃 그려보기

덤벨로퍼 2022. 11. 22. 16:45

 

Modern Collection View 와 MVVM 패턴 가이드

다양한 사이즈 형태의 collection view를 구현 하기 위해 Group을 잘 짜줘야 한다.

let group = NSCollectionLayoutGroup.vertical(
	layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
 heightDimension: .fractionalWidth(16/9)),
 subitems: [다양한 그룹들])

(각 그룹들의 높이는 고정값으로 지정했으니 무시)

위 그룹의 subItems 안에 다양한 타입의 그룹이 들어갈것이고

해당 그룹들은 vertical 하게 들어갈것이다.

 

다음 예시를 통해 여러 타입의 collectionview 를 그려볼것이다.

 

가장 먼저 1번 - 너비는 width * 1

높이는 width * 2/3 크기를 가지고 있다.

let fullItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(2/3)))
//padding 추가
fullItem.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)

해당 fullItem을 가지고 레이아웃을 리턴한다

func generateLayout() -> UICollectionViewLayout {

    
    let fullItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(2/3)))
    fullItem.contentInsets = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)

    
    let group = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(16/9)), subitems: [fullItem])
    let section = NSCollectionLayoutSection(group: group)

    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
  }

그룹 안에 해당 fullitem을 너어주면 모든 아이템들이 fullItem 사이즈로 그려진다.

 

2번 레이아웃

2번 은 두가지 타입으로 나뉜다.

왼쪽의 큰 메인이미지, 오른쪽의 서브이미지그룹

이 두 타입을 그룹으로 묶어야한다. (2번 그룹이라 하자)

2번 그룹의 너비는 width * 1 높이는 width * 4/9 로 지정해줬다.

그리고 두 타입(메인이미지 + 서브그룹) 이미지는 horizontal로 정렬 된다. ( 좌 우로 그려지므로)

let mainAndSubGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(4/9)), subitems: [MainItem, subGroup])

이렇게 그룹을 만들것이다.

구성은 이렇게 된다

  • 전체 그룹
    • 2번 그룹
      • 메인이미지
      • 서브이미지 그룹

이제 들어갈 아이템을 그려본다.

메인이미지는 width * 2/3

높이 height * 1 (2번 그룹의 기준) 를 가진다.

let mainItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(2/3), heightDimension: .fractionalHeight(1.0)))

서브 이미지 그룹의 너비는 width * 1/3

높이는 height * 1 일것이고 ( 2번 그룹 기준)

위아래로 두개 들어갈 서브 이미지의 너비는 width * 1

높이 height * 1/2 사이즈이다.

let subItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1/2)))
let subGroup = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1.0)), subitem: subItem, count: 2)

이제 mainAndSubGroup 을 그룹에 넣어주면

 

 

이렇게 fullItem, mainAndSubGroup 식으로 반복된다.

 

4번 레이아웃

4번은 2번을 반대로 하면 된다. 이미 구현했으니 순서만 바꾼 그룹을 만들면 된다.

let subGroupAndMain = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(4/9)), subitems: [subGroup, mainItem])

3번 레이아웃

3번 - 너비 width * 1/3 인 아이템들을 그룹에 넣어주면된다.

let trippleItme = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1.0)))
    let trippleGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(2/9)), subitem: trippleItme, count: 3)

전체코드

func generateLayout() -> UICollectionViewLayout {
    let contentInset = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)
    
    let fullItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(2/3)))
    fullItem.contentInsets = contentInset

    
    let mainItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(2/3), heightDimension: .fractionalHeight(1.0)))
    mainItem.contentInsets = contentInset
    let subItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1/2)))
    subItem.contentInsets = contentInset
    let trippleItme = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1.0)))
    trippleItme.contentInsets = contentInset

    let trippleGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(2/9)), subitem: trippleItme, count: 3)

    let subGroup = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1.0)), subitem: subItem, count: 2)
    
    let mainAndSubGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(4/9)), subitems: [mainItem, subGroup])
  
    let subGroupAndMain = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(4/9)), subitems: [subGroup, mainItem])

    let group = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(16/9)), subitems: [fullItem, mainAndSubGroup, trippleGroup, subGroupAndMain])
    let section = NSCollectionLayoutSection(group: group)

    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
  }

 

참조 : https://www.kodeco.com/5436806-modern-collection-views-with-compositional-layouts