使用 IGListKit 或 UICollectionView 每行多个部分

Posted

技术标签:

【中文标题】使用 IGListKit 或 UICollectionView 每行多个部分【英文标题】:Multiple Sections Per Row using IGListKit or UICollectionView 【发布时间】:2019-10-24 18:57:08 【问题描述】:

我正在尝试以这种方式创建提要布局

[-------2/3-------][---1/3---] /* 2 items - 2 thirds and 1 third */
[---1/3---][-------2/3-------] /* 2 items - 1 third and 2 thirds */
[-------2/3-------][---1/3---] /* 2 items - 2 thirds and 1 third */
[---1/3---][-------2/3-------] /* 2 items - 1 third and 2 thirds */

我可以通过做类似的事情来实现这一点

class FeedSectionController: ListSectionController 

    var entry: FeedEntry!

    override init() 
        super.init()
        inset = UIEdgeInsets(top: 0, left: 0, bottom: 15, right: 0)
    

    override func numberOfItems() -> Int 
        return 2
    

    override func sizeForItem(at index: Int) -> CGSize 

        guard let ctx = collectionContext else  return .zero 

        if index == 0 
            return CGSize(width: ((ctx.containerSize.width / 3) * 2), height: 30)
         else 
            return CGSize(width: (ctx.containerSize.width / 3), height: 30)
        
    

    override func cellForItem(at index: Int) -> UICollectionViewCell 
        let cell = UICollectionViewCell()
        cell.backgroundColor = index % 2 == 0 ? .lightGray : .darkGray

        return cell
    

    override func didUpdate(to object: Any) 
        entry = object as? FeedEntry
    

但是结果真的更像

[-------2/3-------][---1/3---] /* 2 items - 2 thirds and 1 third */
[-------2/3-------][---1/3---] /* 2 items - 2 thirds and 1 third */
[-------2/3-------][---1/3---] /* 2 items - 2 thirds and 1 third */
[-------2/3-------][---1/3---] /* 2 items - 2 thirds and 1 third */

这不太正确,这也意味着我每个单元格每个部分有 2 个完整的提要项。

我希望每个部分都包含 X 数量的单元格,这些单元格基本上构成了一个提要项。

但要做到这一点,我需要以前面概述的方式布局 FeedSectionController,而不是 FeedSectionController 中的项目(我认为)。

【问题讨论】:

【参考方案1】:

我对 IGListKit 不是 100% 熟悉,但您可以使用标准的 UICollectionView 来创建这种效果


class FeedViewController: UIViewController 

    private enum FeedItemWidth 
        case oneThird, twoThirds
    

    private lazy var collectionView: UICollectionView = 
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell")
        cv.backgroundColor = .gray
        cv.translatesAutoresizingMaskIntoConstraints = false
        return cv
    ()

    override func viewDidLoad() 
        super.viewDidLoad()

        collectionView.delegate = self
        collectionView.dataSource = self

        if let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout 
            collectionViewLayout.minimumInteritemSpacing = 0
            collectionViewLayout.sectionInset = .init(top: 8, left: 8, bottom: 8, right: 8)
        

        view.backgroundColor = .lightGray

        view.addSubview(collectionView)

        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
        ])
    

    override func viewWillLayoutSubviews() 
        super.viewWillLayoutSubviews()
        collectionView.collectionViewLayout.invalidateLayout()
    

    private func feedItemWidth(_ type: FeedItemWidth) -> CGFloat 
        switch type 
        case .oneThird:
            return (collectionView.bounds.width / 3) - 12
        case .twoThirds:
            return  ((collectionView.bounds.width / 3) * 2) - 12
        
    


extension FeedViewController: UICollectionViewDelegateFlowLayout 
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 

        let layoutOptions = [
            CGSize(width: feedItemWidth(.oneThird), height: 100),
            CGSize(width: feedItemWidth(.twoThirds), height: 100),
            CGSize(width: feedItemWidth(.twoThirds), height: 100),
            CGSize(width: feedItemWidth(.oneThird), height: 100)
        ]

        return layoutOptions[indexPath.item % layoutOptions.count]
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat 
        return 8
    



extension FeedViewController: UICollectionViewDataSource 
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 35
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", for: indexPath)
        cell.backgroundColor = (indexPath.item % 2 == 0) ? .white : .black
        return cell
    


【讨论】:

以上是关于使用 IGListKit 或 UICollectionView 每行多个部分的主要内容,如果未能解决你的问题,请参考以下文章

具有部分和多个项目的 IGListKit

如何使用 IGListKit 强制重新加载所有部分?

如何在 swift 中使用 IGListKit 创建一个两列集合视图列表

如何使用 IGListKit 滚动到部分的底部

使用嵌套适配器垂直滚动时出现滞后问题 | IGListKit

IGListKit:获取当前可见的单元格索引