[WWDC2019] Advances in CollectionView Layout

CollectionView Layout의 발전 목차

  1. CollectionView의 현재 기술 (current state of the art)

  2. (iOS, tvOS, MacOS) 새로운 접근 방식 (a new approach)

  3. Demo

  4. 고급 기능 (advanced layouts)


1. CollectionView의 현재 기술 (current state of the art)

UICollectionViewFlowLayout

  1. CollectionViewLayout

    • Layout을 정의하기 위해 두 가지 역할을 가진 클래스로 추상화되어있다.

      • rendering을 하는 class

      • collectionView Layout이 어디로 가는지?에 대해 책임을 지는 class

      • CollectionView Layout은 추상화되어있기 때문에 사용하려면 항상 Subclassing을 해야한다.

        이것을 Concrete type으로 정의한 것이 iOS 6에서 발표했던 CollectionView Flow Layout이다.

  2. CollectionViewFlowLayout

    • line based layout system이었기 때문에, iOS6을 사용했던 환경에서 매우 유용하게 사용됐다.

      • (2018 WWDC 영상 참고) 단순히 Line들을 배치하고, 축을 기반으로 배치해서 Layout을 구성할 수 있다.

      • 매우 간단하고, 추론이 쉬우며, 빠르다는 장점이 있다.

      • 하지만 요즘에 이종화되는 기기와, 다양한 custom layout이 나오면서 UI가 매우 복잡해졌다.


  • 복잡해진 UI로 인해 발생하는 문제점을 살펴보자.

    Untitled
  • AppStore의 메인화면을 구성하기 위해 우리는 다양한 컴포넌트를 고민할 것이다.

    • 다양한 모양의 Cell이 존재하기 때문에, CollectionView를 선택했다고 가정하자.

      이때, “Flow”를 표현할 수 있을지 고민하기 시작하자마자 CollectionView 사용을 포기하게 된다. (이유는 몰까)

  • Custom Layout을 설계할 때 발생할 수 있는 문제점

    • Boilerplate code

    • Performance considerations

    • Supplementary and decoration view challenges

      • CollectionView에서 관리할 수 있는 View, DecorationView는 CustomLayout에서 까다롭게 작용한다.

    • Self-sizing challenges

    ⇒ 이 문제들을 해결하기 위해 Flow와 동일한 Concrete class인 새로운 플랫폼을 도입했으며, 이것이 바로 Compositional Layout이다.


2. 새로운 접근 방식 (a new approach)

Compositional Layout의 개념

  • Compositional Layout의 중심 개념 3가지

    1. Composable

      간단한 것을 이용해서 복잡한 것을 만든다.

    2. Flexible

      유연하게 설계되어, 어떤 레이아웃이든 작성할 수 있다.

    3. Fast

      자체 최적화를 수행하여 빠르다.

  • Compositional Layout은 Layout을 설명하거나, 정의하는 선언형 API이다.

Compositional Layout의 활용

  • Composing small layout groups together

    작은 레이아웃을 만들고, 이들을 조합해서 더 큰 레이아웃을 구성한다.

  • Layout groups are line-based

    FlowLayout의 장점을 이어가기 위해 line based에 따라 레이아웃을 그릴 수 있다. (굉장히 많은 UI)

    작은 레이아웃 그룹을 한 줄로 Item을 배치할 수 있다.

  • composition instead of subclassing

    Subclassing을 하지 않아도 된다. (Concrete type)

    추론 가능한 레이아웃으로 구성할 수 있기 때문에 매우 단순하다.

Compositional Layout Code 및 개념

  • Core Concepts

    Untitled
  • Type(유형)에 대해 자연스러운 Flow가 존재한다.

    • 5가지 유형이 존재한다. (Item, Group, Section, Layout)

      Untitled

Layout Types

  1. Size

    • 모든 것들은 명백한 사이즈를 가지고 있다.

    • 사이즈를 쉽게 추론할 수 있는 방법 (각 Type이 얼마나 큰지 확인)

      Size = Width + Height dimension

    class NSCollectionLayoutSize {
    	init(widthDimension: NSCollectionLayoutDimension,
    			 heightDimension: NSCollectionLayoutDimension)
    }
    • NSCollectionLayoutDimension

      • 축과 무관한 방법으로, 폭과 높이, 차원에 대한 정보만을 이용해서 축의 크기를 설명한다.

        이때, 폭과 높이의 경우, NSCollectionLayoutDimension이라는 새로운 유형으로 정의한다.

      • NSCollectionLayoutDimension의 4가지 유형

        // 축의 크기를 나타내는 "축 독립적 방법"
        class NSCollectionLayoutDimension {
        	class func fractionalWidth(_ fractionalWidth: CGFloat) -> Self 
        	class func fractionalHeight(_ fractionalHeight: CGFloat) -> Self 
        	class func absolute(_ absoluteDimension: CGFloat) -> Self
        	class func estimated(_ estimatedDimension: CGFloat) -> Self
        }
      • 특정 Item의 width = Container 폭의 50%를 차지한다.

        Untitled
      • Item의 Height = Container 폭의 30% 차지

        Untitled
      • 특정 종횡비를 갖도록 정의 (Container의 25%씩 aspect ratio)

        Untitled
      • 정확한 치수를 갖도록 정의 (point based value)

        스크린샷 2023-09-26 오후 12.43.37.png
  2. Item

    • 기존의 Cell의 개념과 동일

      class NSCollectionLayoutItem {
      	convenience init(layoutSize: NSCollectionLayoutSize)
      	var contentInsets: NSDirectionalEdgeInsets
      }
  3. Group

    Untitled
  4. Section (NScollectionLayoutSection)

    • CollectionView의 단면을 기준으로 한 Layou의 정의

    • Section에 몇 개의 항목이 있는지에 대해 DataSource에 직접 매핑되는 개체

    • Initializer가 Group을 허용한다.

      class NSCollectionLayoutSection {
      	convenience init(layoutGroup: NSCollectionLayoutGroup)
      	var contentInsets: NSDirectionalEdgeInsets
      }
  5. Layout

  • 최상위 Layout class

  • iOS, tvOS의 경우, UICollectionViewCompositionalLayout 사용

  • MacOS의 경우, NSViewCompositionalLayout 사용

  • 플랫폼과 상관 없이, 모든 정의가 동일하다.

    class UICollectionViewCompositionalLayout: UIcollectionViewLayout {
    	init(section: NSCollectionViewSection)
    	init(sectionProvider: @escaping SectionProvider)
    }

Last updated