iOS - Compositional Layout CollectionView 사용하기

이한솔·2023년 12월 4일
0

iOS 앱개발 🍏

목록 보기
37/49

Compositional Layout CollectionView 사용하기

섹션을 정의한다.

enum Section: Int, CaseIterable {
    case category
    case product
    case circleItem
}

컬렉션뷰를 생성하고 사용할 셀과 헤더뷰를 등록해준다.

private var collectionView: UICollectionView!

collectionView.register(CategoryCell.self, forCellWithReuseIdentifier: "CategoryCell")
collectionView.register(ProductCell.self, forCellWithReuseIdentifier: "ProductCell")
collectionView.register(CircleItemCell.self, forCellWithReuseIdentifier: "CircleItemCell")
collectionView.register(ItemHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderView")

레이아웃을 설정한다.

collectionView.collectionViewLayout = getLayout()

 func getLayout() -> UICollectionViewCompositionalLayout {
    let layout = UICollectionViewCompositionalLayout { (section, env) -> NSCollectionLayoutSection? in
        switch section {
        // Title 섹션
        case 0:
            let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
            item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 12)
                
            let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(68))
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
                
            let section = NSCollectionLayoutSection(group: group)
            section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 14, bottom: 16, trailing: 14)
            return section
                
        // Product 섹션
        case 1:
            let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
                
            let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(240), heightDimension: .estimated(316))
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
                
            let section = NSCollectionLayoutSection(group: group)
            section.interGroupSpacing = 10
            section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20)
            section.orthogonalScrollingBehavior = .continuous
            return section
                
        // CircleItem 섹션
        case 2:
            let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
                
            let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(80), heightDimension: .estimated(130))
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
                
            // SupplementaryView로 HeaderView 레이아웃설정
            let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(60.0))
            let header = NSCollectionLayoutBoundarySupplementaryItem(
                layoutSize: headerSize,
                elementKind: UICollectionView.elementKindSectionHeader,
                alignment: .top
            )
                
            let section = NSCollectionLayoutSection(group: group)
            section.interGroupSpacing = 10
            section.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 25, bottom: 24, trailing: 25)
            section.orthogonalScrollingBehavior = .continuous
            // HeaderView 등록
            section.boundarySupplementaryItems = [header]
            section.supplementariesFollowContentInsets = false
            // DecoView 생성
            let decorationView = NSCollectionLayoutDecorationItem.background(elementKind: "DecoView")
            section.decorationItems = [decorationView]
            return section
        default:
            return nil
        }   
    }
    // DecorationView 등록
    layout.register(DecoView.self, forDecorationViewOfKind: "DecoView")
    return layout
    
}



// HeaderView 설정
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    switch kind {
    case UICollectionView.elementKindSectionHeader:
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderView", for: indexPath) as! ItemHeaderView
        return header
    default:
        return UICollectionReusableView()
    }
}

DataSource를 설정한다.

collectionView.dataSource = self

// numberOfSections 메소드 구현 (섹션 개수)
func numberOfSections(in collectionView: UICollectionView) -> Int {
    return Section.allCases.count
}

// numberOfItemsInSection 메소드 구현 (섹션의 row 개수)
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    switch Section(rawValue: section) {
    case .category:
        return categoryImage.count
    case .product:
        return productList.count
    case .circleItem:
        return circleItemList.count
    case .none:
        return 0
    }
}

// cellForItemAt 메소드 구현 (셀 내용)
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let currentSection = Item(rawValue: indexPath.section)
    
    switch currentSection {
    case .category:
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell", for: indexPath) as? CategoryCell else { return UICollectionViewCell()}
        cell.titleButton.setImage(categoryImage[indexPath.row], for: .normal)
        return cell
        
    case .product:
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCell", for: indexPath) as? ProductCell else { return UICollectionViewCell() }
        
        let product = productList[indexPath.row]
        cell.productImageView.image = product.image
        cell.contentTitleLabel.text = product.title
        cell.ratingLabel.text = product.rating
        cell.reviewCountLabel.text = "(\(product.reviewCount))"
        cell.locationLabel.text = product.location
        cell.priceLabel.text = product.price
        
        return cell
        
    case .circleItem:
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CircleItemCell", for: indexPath) as? CircleItemCell else { return UICollectionViewCell() }
        
        let item = circleItemList[indexPath.row]
        cell.circleImageView.image = item.image
        cell.circleItemLabel.text = item.title
        
        return cell
    case .none:
        return UICollectionViewCell()
    }
}

0개의 댓글