ios/UI구현

[Swift] UICollectionView - Compositional Layout section의 동적인 높이 조절

2023. 5. 30. 01:41

프로젝트를 진행하던 중 UICollectionView의 Compositional Layout을 사용해 3x3 행렬의 layout을 가지고 9개 이상의 item이 존재한다면 수평스크롤을 통해 다음페이지에 cell을 생성하는 레이아웃을 생성하였습니다.

이때, item의 개수가 0~6개 일때도 설정해둔 fractionalHeight(0.675)로 인해 빈공간이 생기고 0.675의 비율을 넘어서는 공간에 다음섹션이 존재하는 부자연스러운 레이아웃을 생성하여 item의 개수에 따라 해당 섹션의 높이를 지정해주고자 하는데에서 공부하게 되었습니다.

이전의 코드는 다음과 같습니다.

private func brandsSection() -> NSCollectionLayoutSection {
        
        
        // item
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0 / 3.0),
            heightDimension: .estimated(150)
        )
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        item.contentInsets = NSDirectionalEdgeInsets(top: 15, leading: 15, bottom: 15, trailing: 0)
        
        
        
        // group
        let lineGroupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0),
            heightDimension: .estimated(100)
        )
        
        let groupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.92),
            heightDimension: .fractionalHeight(0.675) //화면의 0.675만큼을 차지하는 고정적인 넓이
        )
        
        let lineGroup = NSCollectionLayoutGroup.horizontal(
            layoutSize: lineGroupSize,
            subitem: item,
            count: 3
        )
        
        let group = NSCollectionLayoutGroup.vertical(
            layoutSize: groupSize,
            subitems: [lineGroup]
        )
        
        //header
        let headerSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.9),
            heightDimension: .absolute(40)
        )
        let header = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: headerSize,
            elementKind: UICollectionView.elementKindSectionHeader,
            alignment: .top
        )
        
        
        // section
        let section = NSCollectionLayoutSection(group: group)
        section.orthogonalScrollingBehavior = .groupPaging
        section.boundarySupplementaryItems = [header]
        
        return section
    }

- UICollectionViewDelegateFlowLayout 활용

먼저 UICollectionView의 section높이를 동적으로 지정하기 위해 UICollectionViewDelegateFlowLayout 프로토콜을 활용하였으나,

작동하지 않았고 예상되는 이유는 다음과 같았습니다.

 

- Compositional Layout은 Collection View의 레이아웃을 관리하는 데에 특화된 독립적인 시스템이다.

 

Compositional Layout은 독립적인시스템이기 때문에 UICollectionViewDelegateFlowLayout 프로토콜을 활용하기 위해서는 추가적인 작업이 필요로 했고, 조금 더 직접적인 방법을 고민했습니다.

 

 

- 연산프로퍼티(Computed Property) 활용

섹션에 직접적인 높이를 다루는 필드는  brandSection 메소드이므로, 여기서 높이를 동적으로 변경하여야겠다고 생각했고

item의 개수에따라 높이를 반환하는 변수를 생성했습니다.

또한 item의 크기를 부분적(fractional)으로 준다면 섹션의 크기가 줄어들면서 item의 크기도 줄어들기 때문에 estimated를 활용해 아이템의 크기를 지정했습니다.

(estimated - estimated는 예상치를 사용하여 크기를 결정하는 옵션입니다. 이 옵션은 해당 dimension의 크기를 대략적으로 추정하고, 컨텐츠의 실제 크기에 따라 동적으로 조정될 수 있습니다. estimated 크기는 컨텐츠의 크기나 내용에 따라 유동적으로 변경될 수 있으며, 컨텐츠 크기를 정확히 알 수 없는 경우 유용합니다.)

private var fractionalHeight: Float {
        get {
            switch self.brandList.count {
            case 0...3:
                return 0.225
            case 4...6:
                return 0.45
            default:
                return 0.675
            }
        }
    }
    
    .
    .
    .
    .
    
private func brandsSection() -> NSCollectionLayoutSection {
	let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1.0 / 3.0),
            heightDimension: .estimated(150)
        )
     					.
     					.
     					.
 	let groupSize = NSCollectionLayoutSize(
           	 widthDimension: .fractionalWidth(0.92),
             heightDimension: .fractionalHeight(CGFloat(fractionalHeight))
     )

다음과 같이 아이템의 개수에 따라 item의 개수에 따라 section의 높이가 동적으로 변경되었지만 UI적인 측면에서 animation없이 순간적인 새로고침현상처럼 layout이 변경되어 animation을 주고자 했습니다.

 

- collectionView.performBatchUpdates

  1. performBatchUpdates는 collectionView의 메소드 
  2. insert, delete, reload, move 연산을 그룹으로 묶어서 일괄적으로 animate

위에서 말했듯이 Compositional Layout은 레이아웃을 관리하는 데에 특화된 독립적인 시스템이기 때문에 이외의

UIViewAnimator나 UIViewPropertyAnimator는 동작하지 않는것 같습니다.

따라서 collectionView의 변화에 대해서 performBatchUpdates를 사용한다면 animation효과를 줄 수 있습니다.

self.collectionView.performBatchUpdates(
              {
                  self.collectionView.reloadSections(NSIndexSet(index: 0) as IndexSet)
              }, completion: { (finished:Bool) -> Void in
            })

'ios > UI구현' 카테고리의 다른 글

[iOS, Swift] 네이버지도의 BottomSheet  (0) 2023.07.27
[iOS, Swift] AppStore layout만들어보기(UICollectionView, CompositionalLayout 활용)  (0) 2023.07.27
[iOS, Swift] 네이버 웹툰 메인 페이지(UIPageViewController, UISegnmentControl 활용)  (0) 2023.07.27
[iOS, Swift] Sticky Header(배달의민족, 당근마켓)  (0) 2023.07.27
'ios/UI구현' 카테고리의 다른 글
  • [iOS, Swift] 네이버지도의 BottomSheet
  • [iOS, Swift] AppStore layout만들어보기(UICollectionView, CompositionalLayout 활용)
  • [iOS, Swift] 네이버 웹툰 메인 페이지(UIPageViewController, UISegnmentControl 활용)
  • [iOS, Swift] Sticky Header(배달의민족, 당근마켓)
chobo5
chobo5
개발 기록
전체
오늘
어제
chobo5
chobo5's blog
chobo5
  • 분류 전체보기
    • ios
      • 문법
      • UIKit
      • UI구현
      • 기타
    • IT
    • Java
      • 기초
      • Spring
      • JPA
    • Algorithm
    • OOP
    • SQL

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

태그

  • getter
  • Swift
  • static
  • didset
  • Lazy
  • setter
  • property
  • 프로퍼티
  • restapi
  • API

최근 글

hELLO · Designed By 정상우.
chobo5
[Swift] UICollectionView - Compositional Layout section의 동적인 높이 조절
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.