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

Modern UIKit Collection, TableView #2-1

ARpple 2023. 9. 3. 15:46

Advances in Collection View Layout - 1

 

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 ์ปฌ๋ ‰์…˜์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๊ธฐ๋ณธ ๋ชฉ๋ก๋ถ€ํ„ฐ ๋‹ค์ฐจ์› ํƒ์ƒ‰ ํ™˜๊ฒฝ๊นŒ์ง€ ๋™์ ์ด๊ณ  ๋ฐ˜์‘์ด ๋น ๋ฅธ ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”.

๊ธฐ์กด UICollectionViewFlowLayout ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ 

  1. ๋‹จ์ˆœํ•œ ๊ทธ๋ฆฌ๋“œ ํ˜•์‹์—๋Š” ํฐ ๋„์›€์ด ๋œ๋‹ค.
  2. Line based → ๋‹จ์ผ gird๋งŒ ์ง€์›ํ•œ๋‹ค.
  3. ํ˜„์žฌ๋Š” ์ˆ˜๋งŽ์€ ๋ณต์žกํ•œ ์ปค์Šคํ…€ ๋ ˆ์ด์•„์›ƒ์„ ์ง€์›ํ•ด์•ผํ•œ๋‹ค.
์• ํ”Œ์€ ๊ธฐ์กด Collection Layout ๋ฐฉ์‹์œผ๋กœ ์ƒˆ๋กœ์šด "์•ฑ ์Šคํ† ์–ด" ์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํฌ๊ธฐํ–ˆ๋‹ค...

๊ธฐ์กด ์ปค์Šคํ…€ ๋ ˆ์ด์•„์›ƒ ์ œ์ž‘์˜ ๋ฌธ์ œ์ 

  1. Boilerplate code
    ⇒ ๋‹จ์ˆœ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ
  2. ํผํฌ๋จผ์Šค ๊ณ ๋ ค์‚ฌํ•ญ์˜ ์ฆ๊ฐ€
  3. Supplementary and decoration view challenges
    ⇒ ์…€ ๋ฐ ์„น์…˜์˜ ์ถ”๊ฐ€๋˜๋Š” ๋ทฐ (์„น์…˜ ํ—ค๋”, ํ‘ธํ„ฐ, ์•„์ดํ…œ ๋ฑƒ์ง€ ๋“ฑ๋“ฑ…) ๋งŒ๋“ค๊ธฐ ๋ณต์žกํ•จ
  4. Self-sizing challenges
    ⇒ ์…€ ๋ฐ ์„น์…˜์ด ์ž์ฒด์ ์ธ ์‚ฌ์ด์ฆˆ๋ฅผ ์„ค์ •ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์–ด๋ ค์›€

Compositional Layout์˜ ํŠน์ง•

์ œ์ž‘ ๋ชฉ์ 

  1. Composable (๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•จ) ⇒ ๊ฐ๊ฐ์˜ ์˜์—ญ๋ณ„๋กœ ์ž์ฒด์ ์ธ (์˜ˆ: ์•ฑ์Šคํ† ์–ด์˜ ์ถ”์ฒœ ์•ฑ ๋ฆฌ์ŠคํŠธ) ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ ๊ฐ€๋Šฅ..?
  2. Flexible (์œ ์—ฐํ•จ) ⇒ ์•ฑ์Šคํ† ์–ด ์ •๋„์˜ ๋‹ค์–‘ํ•œ ๋ ˆ์ด์•„์›ƒ์„ ์œ ์—ฐํ•˜๊ฒŒ ์ ์šฉ ๊ฐ€๋Šฅ
  3. Fast (๋น ๋ฆ„) ⇒ ๋ญ๊ฐ€ ๋น ๋ฅด๋‹ค๋Š” ๊ฒƒ์ธ์ง€๋Š” ๋ชจ๋ฅด๊ฒ ๋‹ค.
๐Ÿ’ก ๊ธฐ์กด์—๋Š” ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ CollectionView๋ฅผ ๋งŒ๋“œ๋ ค๋ฉด WrapperCell์„ ๋งŒ๋“ค์–ด์„œ WrapperCell ๋‚ด๋ถ€์— CollectionView๋ฅผ ๋‹ค์‹œ ์ •์˜ํ•˜๋Š” ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ ธ์•ผํ•œ๋‹ค. ํ•˜์ง€๋งŒ Compoisional Layout์˜ ๊ฐœ๋…๊ณผ ๊ตฌ์กฐ๋ฅผ ์ด๋ฃจ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋‹ค์–‘ํ•œ ๋ ˆ์ด์•„์›ƒ์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ WrapperCell๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†๋‹ค..!

๊ธฐ์กด ๋ฐฉ์‹์œผ๋กœ ์•ฑ์Šคํ† ์–ด๋ฅผ ๋งŒ๋“ค๋ฉด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์˜ˆ์‹œ ์ฝ”๋“œ

class CollectionVC: UIViewController{
    let collectionView = UICollectonView()
    ...
    override func viewDidLoad(){
        collectionView.register(BannerSectionWrapperCell.self)
        ...
    }
}
class BannerSectionWrapperCell: UICollectionViewCell{
    let bannerCollectionView = UICollectionView() // <- ์—ฌ๊ธฐ๊ฐ€ ๋ฌธ์ œ..!
// Why? ์ถ”๊ฐ€์ ์ธ Delegate ์ฝ”๋“œ์™€ DataSource ์ฝ”๋“œ ์ž‘์„ฑ ์„ฑ๋Šฅ ๋ฌธ์ œ
// + ๋ฐ์ดํ„ฐ๋ฅผ ViewController์— ๋„˜๊ธฐ๋Š”๋ฐ ๋ณต์žกํ•œ ๋ฌธ์ œ ๋“ฑ๋“ฑ...
    ...
    func configureView(){
            bannerCollectionView.register(BannerItemCell.self) // <- ์—ฌ๊ธฐ๋„ ๋ฌธ์ œ..!
    }
}
class BannerItemCell:UICollectionViewCell{
}

๊ตฌํ˜„ ํŠน์ง•

  • Composing small layout groups together
    ⇒ ์ž‘์€ ๋ ˆ์ด์•„์›ƒ ๊ทธ๋ฃน์„ ํ•จ๊ป˜ ๊ตฌ์„ฑํ•œ๋‹ค.
  • Layout groups are line-based
    ⇒ ํ•˜๋‚˜์˜ ์ˆ˜์ง์„ , ์ˆ˜ํ‰์„  ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃน์„ ํ‘œ์‹œํ•œ๋‹ค.
  • Composition instead of subclassing
    ⇒ ์„œ๋ธŒํด๋ž˜์Šค ๋Œ€์‹  ์ฝœ๋ ‰์…˜ ๋ทฐ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ ๊ฐ€๋Šฅ

์ตœ์†Œ ๊ตฌํ˜„ ๊ตฌ์„ฑ ์š”์†Œ 5๊ฐ€์ง€

  1. NSCollectionLayoutSize
  2. NSCollectionLayoutItem
  3. โญ NSCollectionLayoutGroup
  4. NSCollectionLayoutSection
  5. UICollectionViewCompositionalLayout
  • ๊ตฌํ˜„ ์˜ˆ์‹œ ์ฝ”๋“œ
    func createBasicListLayout() -> NSCollectionViewLayout {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                             heightDimension: .fractionalHeight(1.0))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
      
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                              heightDimension: .absolute(44))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
                                                         subitems: [item])
      
        let section = NSCollectionLayoutSection(group: group)
    
        let layout = NSCollectionViewCompositionalLayout(section: section)
        return layout
    }

๊ธฐ๋ณธ ๋งค์ปค๋‹ˆ์ฆ˜ ์ดํ•ด ๋ฐ ์ •๋ฆฌ

์žฌ๊ท€์ ์ด๊ณ  ๋ฐ˜๋ณต์ ์ธ ๊ตฌ์„ฑ

1. ๊ณ„์ธต ๊ตฌ์กฐ์™€ MainTree

  • Layout์˜ ํฌ๊ธฐ๋Š” CollectionView์˜ ํฌ๊ธฐ๋ฅผ Bounds๋กœ ๋ฐ›๋Š”๋‹ค.
  • Section์€ Layout์—์„œ ์„ค์ •ํ•œ ํฌ๊ธฐ์— Bounds๋กœ ๊ฐ–๋Š”๋‹ค.
  • Group์€ Section์—์„œ ์„ค์ •ํ•œ ํฌ๊ธฐ๋ฅผ Bounds๋กœ ๊ฐ–๋Š”๋‹ค.
  • Item์€ Group์—์„œ ์„ค์ •ํ•œ ํฌ๊ธฐ๋ฅผ Bounds๋กœ ๊ฐ–๋Š”๋‹ค.
  • NSCollectionLayoutSize๋กœ ์ด๋“ค์˜ ํฌ๊ธฐ๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋‹ค.

2. Supplementary & Configuration

  • MainTree์— ์ง์ ‘ ๊ด€์—ฌํ•˜์ง„ ์•Š์ง€๋งŒ MainTree์˜ ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋“ค์„ ๊พธ๋ฏธ๊ฑฐ๋‚˜ ์ปค์Šคํ…€ํ•˜๊ธฐ ์œ„ํ•œ ์ž์ฒด์ ์ธ Configuration์„ ๊ฐ–๊ณ  ์žˆ๋‹ค.
    • ์ด ์ปค์Šคํ…€์€ ์ฃผ๋กœ MainTree์˜ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋“ค ๊ฐ„๊ฒฉ์„ ์ฃผ๊ฑฐ๋‚˜, ์Šคํฌ๋กค ๋ฐฉํ–ฅ์„ ์„ค์ •ํ•˜๋Š” ์ •๋„
  • MainTree ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์ฒด์ ์ธ SubView์˜ ์˜์—ญ์„ ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•ด Supplementary ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ๋‹ค.
    • ์ด Supplementary๋Š” ์ฃผ๋กœ ์ปดํฌ๋„ŒํŠธ์˜ Header, Footer, Badge๋ฅผ ๋‹ด๋‹น

3. Provider with ElementKind & SubItems(Array)

ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์— ๋‹จ์ผ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹Œ ๋‹ค์–‘ํ•œ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ–๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋…