CollectionView - 每个部分的列数不同

Posted

技术标签:

【中文标题】CollectionView - 每个部分的列数不同【英文标题】:CollectionView - Different number of columns in each section 【发布时间】:2018-02-27 19:54:00 【问题描述】:

我想要以下示例的集合视图。但无法弄清楚我该如何实现它。它在第一部分有 3 列,在第二部分有 2 列。

请大家帮忙!!!

【问题讨论】:

@branden 给出的示例可以按您的意愿工作。 【参考方案1】:

覆盖 sizeForItemAtIndexPath 并执行以下操作:

- (NSInteger)itemPerRow:(UICollectionView *)collectionView forSection:(NSInteger)section 
    if (section == 0) 
        return 3;
    

    return 2;


- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 

    NSInteger itemsPerRow = [self itemsPerRow:collectionView forSection:indexPath.section];

    CGFloat itemSpacing = ((UICollectionViewFlowLayout *)collectionViewLayout).minimumInteritemSpacing;

    UIEdgeInsets insets = [self collectionView:collectionView layout:collectionViewLayout insetForSectionAtIndex:indexPath.section];

    CGFloat width = (collectionView.bounds.size.width - (itemSpacing * (itemsPerRow - 1))) - (insets.left + insets.right);
    width /= itemsPerRow;
    return CGSizeMake(floor(width), floor(width));


- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section 

    return UIEdgeInsetsMake(20.0, 20.0, 20.0, 20.0);

这会根据节中每行的项目数以及项目间的间距以及节的插图来计算每个项目的大小。它将“降低” itemWidth 以确保 X 数量的项目适合(由于舍入问题)。

【讨论】:

我认为您的 itemsPerRow 函数名称可能有错字【参考方案2】:

这是一个完整的示例,显示基于部分的不同单元格大小。

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout 

    let data: [ (headerTitle: String, items: [String]) ] = [
        // Section 1
        ("Header 1", ["cell1", "cell2", "cell3", "cell4", "cell5", "cell6"]),

        // Section 2
        ("Header 2", ["cell1", "cell2", "cell3", "cell4", "cell5", "cell6"])
    ]

    // Create collectionView
    lazy var collectionView: UICollectionView = 
        let cv: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: self.layout)
        cv.contentInset.left = self.layout.minimumInteritemSpacing
        cv.contentInset.right = self.layout.minimumInteritemSpacing

        // register cell class
        cv.register(Cell.self, forCellWithReuseIdentifier: Cell.id)

        // register header
        cv.register(Header.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: Header.id)

        // set data source
        cv.dataSource = self
        cv.delegate = self

        return cv
    ()

    // Create collection view layout
    lazy var layout: UICollectionViewFlowLayout = 
        let l: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        l.minimumInteritemSpacing = 5 // horizontal space between cells
        l.minimumLineSpacing = 5 // vertical space between cells

        return l
    ()

    override func viewDidLoad() 
        super.viewDidLoad()
        collectionView.backgroundColor = .white
        view.addSubview(collectionView)
    

    override func viewWillLayoutSubviews() 
        super.viewWillLayoutSubviews()
        collectionView.frame = view.bounds
    

    var threeRowsSize: CGSize 
        // Tell layout to put 3 items in a row
        let width: CGFloat = collectionView.bounds.width/3 - (2 * layout.minimumInteritemSpacing)
        return CGSize(width: width, height: width)
    

    var twoRowsSize: CGSize 
        // Tell layout to put 2 items in a row
        let width: CGFloat = collectionView.bounds.width/2 - (2 * layout.minimumInteritemSpacing)
        return CGSize(width: width, height: width)
    

    func numberOfSections(in collectionView: UICollectionView) -> Int 
        return data.count
    

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return data[section].items.count
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Cell.id, for: indexPath) as! Cell
        cell.textLable.text = data[indexPath.section].items[indexPath.row]

        return cell
    

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView 
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: Header.id, for: indexPath) as! Header

        header.textLable.text = data[indexPath.section].headerTitle

        return header
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize 
        return CGSize(width: collectionView.bounds.width, height: 50)
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,   sizeForItemAt indexPath: IndexPath) -> CGSize 
        if indexPath.section == 0 
            return threeRowsSize//threeRowsSize
        
        return twoRowsSize
    

    // Cell
    final class Cell: UICollectionViewCell 
        static let id: String = "cellId"

        let textLable: UILabel = UILabel()

        override init(frame: CGRect) 
            super.init(frame: frame)
            textLable.textAlignment = .center
            contentView.addSubview(textLable)
            textLable.backgroundColor = .lightGray
        

        required init?(coder aDecoder: NSCoder) 
            fatalError("init(coder:) has not been implemented")
        

        override func layoutSubviews() 
            super.layoutSubviews()
            textLable.frame = bounds

            // Make it somewhat circular
            textLable.layer.cornerRadius = textLable.bounds.width/3
            textLable.layer.masksToBounds = true
        
    

    // Header
    final class Header: UICollectionReusableView 
        static let id: String = "headerId"

        let textLable: UILabel = UILabel()

        override init(frame: CGRect) 
            super.init(frame: frame)
            backgroundColor = .cyan
            textLable.textAlignment = .left
            addSubview(textLable)
        

        required init?(coder aDecoder: NSCoder) 
            fatalError("init(coder:) has not been implemented")
        

        override func layoutSubviews() 
            super.layoutSubviews()
            textLable.frame = bounds
        

    

【讨论】:

以上是关于CollectionView - 每个部分的列数不同的主要内容,如果未能解决你的问题,请参考以下文章

异常:数据中的列数与范围内的列数不匹配

Union All 的列数不匹配

多网格中的列数不起作用!反应虚拟化

java 操作Excel,循环每一行的列,为啥列数不相同呢。

sql插入的列数不确定怎么办

Apple Photos collectionview 捏缩放如何工作?