如何在UICollectionViewCompositionalLayout中使用几种类型的cell?

问题描述 投票:0回答:1

我有一个自写的库,带有

UICollectionViewCompositionalLayout
和不同的 4 单元。我想在我的新项目中使用这个库
UICollectionViewCompositionalLayout
。我只想使用两种类型的细胞。不是全部。我正在使用此代码将代码从我的库加载到我的新项目中。但我不知道如何在我当前的
NewViewController
中写出只应该使用两个单元格。怎么做?我想创建一个包含许多不同单元的库。在以后的项目中,我所要做的就是将单元格导入到我的
NewViewController
中,而不是一遍又一遍地编写单元格代码。

我的NewViewController代码:

import UIKit
import MyTestLibrary

class NewViewController: UIViewController {

    let shopViewController = ShopViewController()

    override func viewDidLoad() {
        super.viewDidLoad()
        shopViewController.createCollectionView()
        view.addSubview(shopViewController.collectionView)
    }

// some code to use only 2 cell

}

我的图书馆代码:

import UIKit
public class ShopViewController: UIViewController {
    
    ///` create collection view
    public var collectionView: UICollectionView!
    
    ///` load data source from Section, Book files
    public var dataSource: UICollectionViewDiffableDataSource<Section, Book>?
    
    ///` load data from JSON file
    public let sections = Bundle.main.decode([Section].self, from: "appstore.json")
    
    public override func viewDidLoad() {
        super.viewDidLoad()
        createCollectionView()
    }
    
    public func createCollectionView() {
        
        collectionView = UICollectionView(
            frame: view.bounds,
            collectionViewLayout: createCompositionalLayout())
        
        collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        
        collectionView.backgroundColor = .systemBackground
        
        view.addSubview(collectionView)

        ///` register section header
        
        collectionView.register(SectionHeader.self, 
                                forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                                withReuseIdentifier: SectionHeader.reuseIdentifier)
        
        ///` register cells
        
        collectionView.register(FeaturedCell.self,
                                forCellWithReuseIdentifier: FeaturedCell.reuseIdentifier)
        
        collectionView.register(MediumTableCell.self,
                                forCellWithReuseIdentifier: MediumTableCell.reuseIdentifier)
        
        collectionView.register(SmallTableCell.self,
                                forCellWithReuseIdentifier: SmallTableCell.reuseIdentifier)
        
        collectionView.register(ListTableCell.self,
                                forCellWithReuseIdentifier: ListTableCell.reuseIdentifier)

        createDataSource()
        reloadData()
        
    }

    public func configure<T: SelfConfiguringCell>(_ cellType: T.Type, with book: Book, for indexPath: IndexPath) -> T {
        
        guard let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: cellType.reuseIdentifier,
            for: indexPath) as? T else {
            fatalError("Unable to dequeue \(cellType)")
        }

        cell.configure(with: book)
        
        return cell
    }

    public func createDataSource() {
        
        dataSource = UICollectionViewDiffableDataSource<Section, Book>(collectionView: collectionView) { collectionView, indexPath, book in
            
            switch self.sections[indexPath.section].type {
            case "mediumTable":
                return self.configure(MediumTableCell.self, with: book, for: indexPath)
            case "smallTable":
                return self.configure(SmallTableCell.self, with: book, for: indexPath)
            case "listTable":
                return self.configure(ListTableCell.self, with: book, for: indexPath)
            default:
                return self.configure(FeaturedCell.self, with: book, for: indexPath)
            }
        }

        dataSource?.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in
            
            guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(
                ofKind: kind,
                withReuseIdentifier: SectionHeader.reuseIdentifier,
                for: indexPath) as? SectionHeader else {
                return nil
            }
            
            guard let firstBook = self?.dataSource?.itemIdentifier(
                for: indexPath) else {
                return nil
            }
            
            guard let section = self?.dataSource?.snapshot().sectionIdentifier(
                containingItem: firstBook) else {
                return nil
            }
            
            if section.title.isEmpty {
                return nil
            }
            
            sectionHeader.title.text = section.title
            
            sectionHeader.subtitle.text = section.subtitle
            
            return sectionHeader
        }
    }

    public func reloadData() {
        
        var snapshot = NSDiffableDataSourceSnapshot<Section, Book>()
        snapshot.appendSections(sections)

        for section in sections {
            snapshot.appendItems(section.items, toSection: section)
        }

        dataSource?.apply(snapshot)
    }

    public func createCompositionalLayout() -> UICollectionViewLayout {
        
        let layout = UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
            
            let section = self.sections[sectionIndex]

            switch section.type {
            case "mediumTable":
                return self.createMediumTableSection(using: section)
            case "smallTable":
                return self.createSmallTableSection(using: section)
            case "listTable":
                return self.createListTableSection(using: section)
            default:
                return self.createFeaturedSection(using: section)
            }
        }
        
        let config = UICollectionViewCompositionalLayoutConfiguration()
        config.interSectionSpacing = 20
        layout.configuration = config
        
        return layout
    }

    public func createSectionHeader() -> NSCollectionLayoutBoundarySupplementaryItem {
        
        let layoutSectionHeaderSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.93),
            heightDimension: .estimated(80))
        
        let layoutSectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: layoutSectionHeaderSize,
            elementKind: UICollectionView.elementKindSectionHeader,
            alignment: .top)
        
        return layoutSectionHeader
    }

    public func createFeaturedSection(using section: Section) -> NSCollectionLayoutSection {
        
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .fractionalHeight(1))

        let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
        
        layoutItem.contentInsets = NSDirectionalEdgeInsets(
            top: 0,
            leading: 5,
            bottom: 0,
            trailing: 5)

        let layoutGroupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.93),
            heightDimension: .estimated(288))
        
        let layoutGroup = NSCollectionLayoutGroup.horizontal(
            layoutSize: layoutGroupSize,
            subitems: [layoutItem])

        let layoutSection = NSCollectionLayoutSection(group: layoutGroup)
        
        layoutSection.orthogonalScrollingBehavior = .groupPagingCentered
        
        return layoutSection
    }
    
    public func createListTableSection(using section: Section) -> NSCollectionLayoutSection {
        
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1/3),
            heightDimension: .fractionalHeight(1))
        
        let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
        
        layoutItem.contentInsets = NSDirectionalEdgeInsets(
            top: 8,
            leading: 8, 
            bottom: 8,
            trailing: 8)
        
        let layoutGroupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.93),
            heightDimension: .fractionalWidth(0.5))
        
        let layoutGroup = NSCollectionLayoutGroup.horizontal(
            layoutSize: layoutGroupSize,
            subitems: [layoutItem])

        let layoutSection = NSCollectionLayoutSection(group: layoutGroup)
        
        layoutSection.orthogonalScrollingBehavior = .groupPagingCentered

        return layoutSection
    }

    public func createMediumTableSection(using section: Section) -> NSCollectionLayoutSection {
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .fractionalHeight(0.33))

        let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
        layoutItem.contentInsets = NSDirectionalEdgeInsets(
            top: 0,
            leading: 5,
            bottom: 0,
            trailing: 5)

        let layoutGroupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.93),
            heightDimension: .fractionalWidth(0.55))
        
        let layoutGroup = NSCollectionLayoutGroup.vertical(
            layoutSize: layoutGroupSize,
            subitems: [layoutItem])

        let layoutSection = NSCollectionLayoutSection(
            group: layoutGroup)
        
        layoutSection.orthogonalScrollingBehavior = .groupPagingCentered

        let layoutSectionHeader = createSectionHeader()
        
        layoutSection.boundarySupplementaryItems = [layoutSectionHeader]

        return layoutSection
    }

    public func createSmallTableSection(using section: Section) -> NSCollectionLayoutSection {
        
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .fractionalHeight(0.2))
        
        let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
        
        layoutItem.contentInsets = NSDirectionalEdgeInsets(
            top: 0,
            leading: 20, 
            bottom: 0,
            trailing: 0)

        let layoutGroupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(0.93),
            heightDimension: .estimated(200))
        
        let layoutGroup = NSCollectionLayoutGroup.vertical(
            layoutSize: layoutGroupSize,
            subitems: [layoutItem])

        let layoutSection = NSCollectionLayoutSection(
            group: layoutGroup)
        
        let layoutSectionHeader = createSectionHeader()
        
        layoutSection.boundarySupplementaryItems = [layoutSectionHeader]

        return layoutSection
    }
}
ios swift uicollectionview
1个回答
0
投票

听起来您想跳过某些部分,即使它们已配置和定义。我可以看到在你的实现中你正在这样做:

public func reloadData() {
    
    var snapshot = NSDiffableDataSourceSnapshot<Section, Book>()
    snapshot.appendSections(sections)

    for section in sections {
        snapshot.appendItems(section.items, toSection: section)
    }

    dataSource?.apply(snapshot)
}

将其更改为这样的内容:

public func reloadData() {
    
    var snapshot = NSDiffableDataSourceSnapshot<Section, Book>()
    var sectionsToInsert = sections.filter { eachSection in
        //in order to skip sections (so that they are not visible in the collection view)
        //simply do not append those sections to the data source
        if someCriteria { //you determine what the criteria is
            return true
        }
    }

    snapshot.appendSections(sectionsToInsert)

    for eachSection in sectionsToInsert {
        //you can also hide sections by also not appending any items to that section
        //if you do this, technically the section will still be there with 0 height
        //however, if your section has any padding/margins, since the section is created earlier
        //you will see the padding as specified in your layout 
        if anotherCriteria { //you determine what the criteria is
            snapshot.appendItems(eachSection.items, toSection: eachSection)
        }
    }

    dataSource?.apply(snapshot)
}
© www.soinside.com 2019 - 2024. All rights reserved.