์ด๋ชจ์ €๋ชจ/UIKit

Modern UIKit Collection, TableView #2-2

ARpple 2023. 9. 3. 17:02

Advances in Collection View Layout #2

 

Advances in Collection View Layout - WWDC19 - Videos - Apple Developer

Collection View Layouts make it easy to build rich interactive collections. Learn how to make dynamic and responsive layouts that range...

developer.apple.com

๐Ÿ’ก Collection View Layout์„ ์‚ฌ์šฉํ•˜๋ฉด ํ’๋ถ€ํ•œ interactive ์ปฌ๋ ‰์…˜์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๋ชฉ๋ก๋ถ€ํ„ฐ ๋‹ค์ฐจ์› ํƒ์ƒ‰ ํ™˜๊ฒฝ๊นŒ์ง€ ๋™์ ์ด๊ณ  ๋ฐ˜์‘์ด ๋น ๋ฅธ ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”.

CompositonalLayout ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ

1. NSCollectionLayoutSize

→ Item๊ณผ Group ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•จ

2. NSCollectionLayoutItem

์ปฌ๋ ‰์…˜ ๋ทฐ ๋ ˆ์ด์•„์›ƒ์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค.

⇒ ์ฃผ์š” Property

  • supplementaryItems → ๊ฐ๊ฐ์˜ ์•„์ดํ…œ์— ์ถ”๊ฐ€๋กœ ๋ง๋ถ™์ด๋Š” ์•„์ดํ…œ
  • edgeSpacing → ์•„์ดํ…œ๋“ค ์‚ฌ์ด์— ๋„ฃ๋Š” ๊ฐ„๊ฒฉ
  • contentInsets → ์•„์ดํ…œ ๋‚ด๋ถ€์—์„œ ๊ฐ–์„ ๊ฐ„๊ฒฉ
โœ…  Item์€ supplementaryItem๋“ค์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

3. NSCollectionLayoutGroup

๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ํ•ญ๋ชฉ์„ ๋ฐฐ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ ์ง‘ํ•ฉ์„ ์œ„ํ•œ ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค.

โš ๏ธ NSCollectionLayoutItem์„ ์ƒ์† ๋ฐ›๋Š”๋‹ค!!

⇒ ์ฃผ์š” Property

  • subitems → ๊ทธ๋ฃน์„ ๊ตฌ์„ฑํ•  Item ๋ฐฐ์—ด, ์•ž์„œ Group์˜ Item ๋ฐฐ์—ด ๋ฐฐ์น˜๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ์ง€ ์„ ์–ธํ•ด์•ผํ•œ๋‹ค.
  • interItemSpacing → ์•„์ดํ…œ ๊ฐ„์˜ ๊ฐ„๊ฒฉ์„ ์–ด๋–ป๊ฒŒ ํ•  ์ง€ ์„ค์ •ํ•œ๋‹ค.

⇒ ์ƒ์„ฑ ๋ฐฉ๋ฒ• - 3๊ฐ€์ง€ ํƒ€์ž… ์†์„ฑ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ธฐ

  1. ํ–‰ ๋ฐฐ์—ด์œผ๋กœ ์ƒ์„ฑํ•˜๊ธฐ
  2. ์—ด ๋ฐฐ์—ด๋กœ ์ƒ์„ฑํ•˜๊ธฐ
  3. ์ปค์Šคํ…€ ๊ทธ๋ฃน ์ƒ์„ฑํ•˜๊ธฐ
    ์ง์ ‘ ๊ทธ๋ฃน ๋‚ด๋ถ€ ์˜์—ญ์— ์•„์ดํ…œ๋“ค์˜ ์œ„์น˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค… ๊ทธ๋Ÿฌ๋‚˜ ์ž˜ ์‚ฌ์šฉ ์•ˆํ•˜๋Š” ๋“ฏ…
โœ… Group๋„ NSCollectionLayoutItem์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— Group์˜ subItem์— Group์ธ์Šคํ„ด์Šค๋ฅผ ๋„ฃ์–ด๋„ ๋œ๋‹ค. ์ด๋Ÿฐ ๊ธฐ๋ฒ•์„ Nested group์ด๋ผ ๋ถ€๋ฅธ๋‹ค.

4. NSCollectionLayoutSection

๊ทธ๋ฃน ์ง‘ํ•ฉ์„ ๋ณ„๊ฐœ์˜ ์‹œ๊ฐ์  ๊ทธ๋ฃน์œผ๋กœ ๊ฒฐํ•ฉํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค.

⇒ ์ƒ์„ฑํ•˜๊ธฐ

  1. .init(group: NSCollectionLayoutGroup) → ๊ทธ๋ฃน์„ ๋„ฃ์–ด์„œ ์ƒ์„ฑ
  2. .list(using: [UICollectionLayoutListConfiguration],
    layoutEnvironment: [NSCollectionLayoutEnvironment]) ⇒ List ํ˜•์‹์˜ Section ์ƒ์„ฑ
    โ— WWDC 20 ์ดํ›„์— ๋‚˜์˜จ ๊ฐœ๋…: Lists in UICollectionView ์—์„œ ๋ฌด์—‡์ธ์ง€ ํ™•์ธํ•˜๊ธฐ

⇒ ์ฃผ์š” ์†์„ฑ

  • ์„น์…˜ ์Šคํฌ๋กค ๊ตฌ์ฒดํ™”ํ•˜๊ธฐ
    1. orthogonalScrollingBehavior: [UICollectionLayoutSectionOrthogonalScrollingBehavior]
      ⇒ ์ด Section์„ ๊ฐ–๋Š” CollectionView์˜ ์Šคํฌ๋กค ๋ฐฉํ–ฅ๊ณผ ์ˆ˜์ง ๋ฐฉํ–ฅ์˜ ์Šคํฌ๋กค์˜ ์ •์˜
  • ์„น์…˜ Spacing ๊ตฌ์„ฑํ•˜๊ธฐ
    1. interGroupSpacing → ๊ทธ๋ฃน๋“ค ๊ฐ„์˜ Spacing ์„ค์ •
    2. contentInsets → Section ๋‚ด๋ถ€์™€ ๊ทธ boundary(header, footer)๊ฐ„์˜ ๊ฐ„๊ฒฉ ์„ค์ •
  • ์ถ”๊ฐ€์ ์ธ ๋ทฐ๋“ค ๊ตฌ์„ฑํ•˜๊ธฐ
    1. boundarySupplementaryItems → Header,Footer๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    2. decorationItems → Section์˜์—ญ์— backgroundView๋“ค์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
โœ… Section์€ boundarySupplyItem๊ณผ decorationItem์„ ๊ฐ–๋Š”๋‹ค.

5. NSCollectionViewCompositionalLayout

์œ ์—ฐํ•œ ์‹œ๊ฐ์  ๋ฐฐ์—ด๋กœ ํ•ญ๋ชฉ์„ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ ˆ์ด์•„์›ƒ ๊ฐœ์ฒด์ž…๋‹ˆ๋‹ค.

⇒ ์ƒ์„ฑํ•˜๊ธฐ

  • ๋‹จ์ผ Section ์ปดํฌ๋„ŒํŠธ๋กœ ์กด์žฌํ•˜๋Š” CollectionView ๋งŒ๋“ค๊ธฐ
  • NSCollectionViewCompositionalLayout(section: section)
  • ์—ฌ๋Ÿฌ Section ์ปดํฌ๋„ŒํŠธ๋กœ ์กด์žฌํ•˜๋Š” CollectionView ๋งŒ๋“ค๊ธฐ
  • NSCollectionViewCompositionalLayout(sectionProvider: NSCollectionViewCompositionalLayoutSectionProvider)
โœ… 1. Configuration์œผ๋กœ ์ถ”๊ฐ€์ ์ธ Section๋“ค ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด "NSCollectionViewCompositionalLayoutConfiguration" ํ™•์ธํ•˜๊ธฐ
+  2. ์—ฌ๋Ÿฌ Section์œผ๋กœ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ "NSCollectionViewCompositionalLayoutSectionProvider" ํ™•์ธํ•˜๊ธฐ


CompositonalLayout ๊ตฌ์„ฑ ์ปดํฌ๋„ŒํŠธ

1. Size ์„ค์ •ํ•˜๊ธฐ

NSCollectionLayoutDimension

์ปฌ๋ ‰์…˜ ๋ทฐ์—์„œ ํ•ญ๋ชฉ์˜ ๋„ˆ๋น„ ๋˜๋Š” ๋†’์ด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐœ๋ณ„์ ์ธ ์˜์—ญ์ž…๋‹ˆ๋‹ค.

→ NSCollectionLayoutSize๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.

๐Ÿ’ก CollectionView์—์„œ ๋‚˜ํƒ€๋‚ผ ๊ฐ๊ฐ์˜ ํ•ญ๋ชฉ(Item, Group, Section ๋“ฑ๋“ฑ…)์—์„œ์˜ ๊ณ ์œ  ๋†’์ด ๋ฐ ๋„ˆ๋น„๊ฐ’์„ ์ง€์ •ํ•˜๋Š” ์—ญํ• 
⇒ 3๊ฐ€์ง€์˜ ํ‘œํ˜„๋ฒ•์œผ๋กœ ๋‚˜๋ˆ”

ํ‘œํ˜„๋ฒ• 3๊ฐ€์ง€

  1. Absolute(CGFloat) → ๊ณ ์œ ํ•œ point์˜ ํฌ๊ธฐ๋กœ ์„ค์ •ํ•œ๋‹ค.
  2. Estimated(CGFloat) → ์›ํ•˜๋Š” ํฌ๊ธฐ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์—์„œ ์‹ค์ œ ์ปฌ๋ ‰์…˜ ๋ทฐ์—์„œ์˜ ํฌ๊ธฐ์— ๋งž๊ฒŒ ์„ค์ •ํ•œ๋‹ค.
    ⇒ ํŒŒ์›Œํฌ์ธํŠธ ์ž๋™ ๋งž์ถค ๊ธฐ๋Šฅ๊ณผ ๋น„์Šท
  3. fractionalHeight(CGFloat) - fractionalWidth(CGFloat) → ์ด ํ•ญ๋ชฉ์˜ ์ƒ์œ„ ๊ทธ๋ฃน์˜ ํฌ๊ธฐ์— ๋งž๊ฒŒ ์„ค์ •ํ•œ๋‹ค.

2. Supplymentary ์„ค์ •ํ•˜๊ธฐ

NSCollectionLayoutSupplementaryItem

์ปฌ๋ ‰์…˜ ๋ณด๊ธฐ์—์„œ ํ•ญ๋ชฉ์— ์‹œ๊ฐ์  ์žฅ์‹์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐœ์ฒด์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก ๋ณด์กฐ ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ˜ํ…์ธ ์— ์ถ”๊ฐ€ ๋ณด๊ธฐ๋ฅผ ์ฒจ๋ถ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+  ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•ญ๋ชฉ์— ๋ฐฐ์ง€๋ฅผ ์ฒจ๋ถ€ํ•˜๊ฑฐ๋‚˜ ๊ทธ๋ฃน ์ฃผ์œ„์— ํ”„๋ ˆ์ž„์„ ์ฒจ๋ถ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
+  ๋ณด์กฐ ํ•ญ๋ชฉ์€ ์ฒจ๋ถ€๋œ ํ•ญ๋ชฉ์˜ ์ธ๋ฑ์Šค ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

⇒ ์ฃผ์š” Property

  • containerAnchor → Item๊ณผ ๊ทธ ์ƒ์œ„ Container์™€์˜ ๊ฒฝ๊ณ„์—์„œ ์„ค์ •ํ•  ์œ„์น˜
  • itemAnchor → ์•„์ดํ…œ์— supplementaryItem์„ ๋„ฃ์„ ๊ฒฝ์šฐ ์„ค์ •ํ•  ์œ„์น˜
  • elementKind → ์ด ์•„์ดํ…œ์˜ ๊ณ ์œ  ์•„์ด๋”” (String)
  • zIndex → ์•„์ดํ…œ๋“ค ๊ฐ„์˜ ์Šคํƒ ์ˆœ์„œ

NSCollectionLayoutBoundarySupplementaryItem

์ปฌ๋ ‰์…˜ ๋ณด๊ธฐ์— header ๋˜๋Š” footer๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐœ์ฒด์ž…๋‹ˆ๋‹ค.

NSCollectionLayoutSupplementaryItem ์˜ ์ž์‹ ํด๋ž˜์Šค

๐Ÿ’ก ๊ฒฝ๊ณ„ ์ถ”๊ฐ€ ํ•ญ๋ชฉ์€ ํŠน์ˆ˜ํ•œ ์œ ํ˜•์˜ ์ถ”๊ฐ€ ํ•ญ๋ชฉ(NSCollectionLayoutSupplementaryItem)์ž…๋‹ˆ๋‹ค. ๊ฒฝ๊ณ„ ๋ณด์กฐ ํ•ญ๋ชฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปฌ๋ ‰์…˜ ๋ณด๊ธฐ์˜ ์„น์…˜ ๋˜๋Š” ์ „์ฒด ์ปฌ๋ ‰์…˜ ๋ณด๊ธฐ์— ๋จธ๋ฆฌ๊ธ€ ๋˜๋Š” ๋ฐ”๋‹ฅ๊ธ€์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    let section = NSCollectionLayoutSection(group: group)
    
    let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                                 heightDimension: .estimated(44))
    let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize,
                                                                   elementKind: ElementKind.sectionHeader,
                                                                     alignment: .top)
    let sectionFooter = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize,
                                                                   elementKind: ElementKind.sectionFooter,
                                                                     alignment: .bottom)
        
    section.boundarySupplementaryItems = [sectionHeader, sectionFooter]

NSCollectionLayoutDecorationItem

์ปฌ๋ ‰์…˜ ๋ทฐ์˜ ์„น์…˜์— ๋ฐฐ๊ฒฝ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐœ์ฒด์ž…๋‹ˆ๋‹ค.

[NSCollectionLayoutSupplementaryItem] ์˜ ์ž์‹ ํด๋ž˜์Šค

3. NSCollectionViewCompositionalLayout ๊ตฌ์„ฑ์š”์†Œ

NSCollectionLayoutEnvironment

๋ ˆ์ด์•„์›ƒ์˜ ์ปจํ…Œ์ด๋„ˆ ๋ฐ ํ™˜๊ฒฝ ํŠน์„ฑ(์˜ˆ: ํฌ๊ธฐ ํด๋ž˜์Šค ๋ฐ ๋””์Šคํ”Œ๋ ˆ์ด ๋ฐฐ์œจ) ์ •๋ณด ์ œ๊ณต์— ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœํ† ์ฝœ

let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,
    layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection in

    if layoutEnvironment.traitCollection.userInterfaceStyle == .dark {
        return sectionForUserInterfaceStyle(.dark)
    } else {
        return sectionForUserInterfaceStyle(.light)
    }
}
โœ… ๊ธฐ๊ธฐ์˜ ํŠน์„ฑ๊ณผ ๊ด€๋ จ๋œ ํ™˜๊ฒฝ์„ ์•Œ๋ ค์ฃผ๋Š” ํ”„๋กœํ† ์ฝœ

UICollectionLayoutSectionOrthogonalScrollingBehavior

์ฃผ ๋ ˆ์ด์•„์›ƒ ์ถ•๊ณผ ๊ด€๋ จ๋œ ๋ ˆ์ด์•„์›ƒ ์„น์…˜์˜ ์Šคํฌ๋กค ๋™์ž‘์ž…๋‹ˆ๋‹ค. enum

๐Ÿ’ก ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ ์„น์…˜์€ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ์˜ ์Šคํฌ๋กค ๋ฐฉํ–ฅ ์†์„ฑ์— ์˜ํ•ด ์ •์˜๋œ ๋ ˆ์ด์•„์›ƒ์˜ ์ฃผ์ถ•์„ ๋”ฐ๋ผ ์ฝ˜ํ…์ธ ๋ฅผ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.
+  ํŠน์ • ์„น์…˜์— ๋Œ€ํ•œ ์ด ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ํ•ด๋‹น ์„น์…˜์˜ ์ง๊ต ์Šคํฌ๋กค๋ง ๋™์ž‘ ์†์„ฑ์„ ๊ธฐ๋ณธ๊ฐ’์ธ UICollectionLayoutSectionOrthogonalScrollingBehavior.none๊ณผ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
+  ์ด ์†์„ฑ์— ๋‹ค๋ฅธ ๊ฐ’์„ ์„ค์ •ํ•˜๋ฉด ์„น์…˜์˜ ์ฝ˜ํ…์ธ ๊ฐ€ ์ฃผ ๋ ˆ์ด์•„์›ƒ ์ถ•์— ์ง๊ฐ์œผ๋กœ ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค.

⇒ Enum case

case none
→ ์ฝ˜ํ…์ธ ๋ฅผ ์ง๊ฐ์œผ๋กœ ์Šคํฌ๋กคํ•˜์ง€ ์•Š์Œ

case continuous

→ ์—ฐ์† ์Šคํฌ๋กค์„ ํ†ตํ•ด ์ฝ˜ํ…์ธ ๋ฅผ ์ง๊ฐ์œผ๋กœ ์Šคํฌ๋กคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

case continuousGroupLeadingBoundary

→ ์Šคํฌ๋กคํ•˜์—ฌ ํ‘œ์‹œ๋˜๋Š” ๊ทธ๋ฃน์˜ ์•ž์ชฝ ๊ฒฝ๊ณ„์—์„œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฉˆ์ถค

case paging

→ ์ฝ˜ํ…์ธ  ํŽ˜์ด์ง€๋กœ ์ด๋™ + ๋””๋ฐ”์ด์Šค์˜ ๋„ˆ๋น„, ๋†’์ด๋กœ ์กฐ์ ˆํ•œ๋‹ค.

case groupPaging

→ ์ฝ˜ํ…์ธ ๋ฅผ ํ•œ ๋ฒˆ์— ํ•œ ๊ทธ๋ฃน์”ฉ ์ง๊ฐ์œผ๋กœ ํŽ˜์ด์ง€์— ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

case groupPagingCentered

→ ํŽ˜์ด์ง€์‹œ ๊ทธ๋ฃน ์ค‘์‹ฌ์— ๋‚˜ํƒ€๋‚จ