Compositional Layout

고양이발냄새·2023년 8월 24일
0
UICollectionView(frame: .zero, collectionViewLayout: $$$$$$$)

collectionviewLayout 부분에 UICollectionViewCompositionalLayout()을 넣어주면 된다

보통 Helper를 이용해서 만들어준뒤에 넣어준다

Compositional Layout을 만들때는 3가지가 필요하다

  1. item
  2. group
  3. section
private func makeLayout() -> UICollectionViewCompositionalLayout {
        UICollectionViewCompositionalLayout { [ weak self ]sectionIndex, layoutEnviro in
            guard let self else { return nil}
            let section = self.sections[sectionIndex]
            switch section {
            case .first:
                
                let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
                item.contentInsets = .init(top: 1, leading: 5, bottom: 1, trailing: 5)
                let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .absolute(70), heightDimension: .absolute(70)), subitems: [item])
                
                let section = NSCollectionLayoutSection(group: group)
                section.orthogonalScrollingBehavior = .continuous
                section.interGroupSpacing = 10
                section.boundarySupplementaryItems = [supplementaryHeaderItem()]
                return section
                
            case .second:
                let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1)))
                item.contentInsets = .init(top: 3, leading: 3, bottom: 3, trailing: 3)
                
                let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(50)), repeatingSubitem: item, count: 4)
                
                
                let section = NSCollectionLayoutSection(group: group)
                section.boundarySupplementaryItems = [supplementaryHeaderItem()]
                
                return section
                
                
                
            case .third:
                let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
                item.contentInsets = .init(top: 10, leading: 10, bottom: 10, trailing: 10)
                
                let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(0.4)), repeatingSubitem: item, count: 1)
                
                let section = NSCollectionLayoutSection(group: group)
                
                section.boundarySupplementaryItems = [supplementaryHeaderItem()]
                section.orthogonalScrollingBehavior = .groupPaging
                return section
                
            }
        }
        
    }


헤더나 푸터를 만들때 이런식으로 레지스터 해서 사용을 해주고

dataSource?.supplementaryViewProvider = { (collectionView, kind, indexPath) in
                    guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: Header.identifier, for: indexPath) as? Header else {
                        fatalError("Could not dequeue sectionHeader: \(Header.identifier)")
                    }

                    
                    return sectionHeader
                }

configureDataSource를 할때 넣어준다

 private func supplementaryHeaderItem() -> NSCollectionLayoutBoundarySupplementaryItem    {
        let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .estimated(20)), elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
//        header.pinToVisibleBounds = true
        return header
    }
let config = UICollectionViewCompositionalLayoutConfiguration()
layout.configuration = config

// config에서 줄수있는 세팅은 다음과 같다
1. 전체 섹션의 스크롤 방향(각 섹션마다 스크롤방향을 다르게 쓰고싶다면 각 섹션에 들어가서 수정해줘야 한다)
config.scrollDirection = .horizontal
2. 각섹션각의 스페이싱
config.interSectionSpacing = 20
3. 헤더와 풋터를 전체 섹션에 다 넣어줄수도 있따

ompositional Layout을 대충만들었는데 정확하게 만드는 방법은 이렇다

// 우선 사이즈를 정해준다
let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(150))
// 헤더를 만들어주는데 첫번째 인자에서 사이즈를 넣어주고, 두번째는 뭔지 모름, 세번째는 얼라인먼트? bottom에다가 넣으면 bottom으로 들어갈까?
마지막은 offset. 보통은 y축만 수정하게 된다
let layoutHeader1 = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: "Header1", alignment: .top, absoluteOffset: CGPoint(x: 0, y: -60))

위에서 적은거처럼 diffableDataSource를 쓸경우에는 diffableDataSource안에서 supplementary provider에서 리턴해주도록 한다

compositional Layout 자료
https://medium.com/@hdmdhr/pin-header-to-the-top-in-a-multi-sections-uicollectionview-9f1103f247a5

***Section에 BackgroundView 넣는법*

  1. Custom Class로 CollectionView ReusableView를 만듬
  2. Compositional layout 전체에다가 레지스터를 해줌 (전체 레이아웃임, 섹션 레이아웃 아님)
 layout.register(BackgroundReusableView.self,
                        forDecorationViewOfKind: BackgroundReusableView.identifier)
                        
  // 섹션 layout으로 가서 이니셜라이징 해줌
  let backgroundItem = NSCollectionLayoutDecorationItem.background(elementKind: BackgroundReusableView.identifier)
  // 컨텐트 인셋도 똑같이 줌
  backgroundItem.contentInsets = section.contentInsets
  // 섹션레이아웃에 추가해줌
  section.decorationItems = [backgroundItem]

compositional을 쓸때는 레이아웃에 헤더를 만들어주어야한다 이녀석은 단지 레이아웃을 어떻게 그릴지만 정해준다
그리고 diffable DataSource를 쓸때는 DataSource 에 어떤 섹션에서 어떤게 불릴지를 불러주고
그냥쓴다면 여기에 넣어준다

 func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: CommentHeaderView.identifier, for: indexPath)
        
        return view
    }
profile
고양이좋아

0개의 댓글