如何设置自定义 UICollectionView 单元格大小

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

社区您好,我想实现一个 UICollectionviewCell,其大小为 110,每行最初有 3 个单元格

1.) 现在需要做一些修改,这样第一行应该有 3 个单元格,但第二行应该有 2 个单元格

2.) 第一个单元格大小应为 220,第二个单元格大小保持不变 110

3.) 在第三行中,它将具有与第一行相同的结构

4.) 但在第 4 行,第一个单元格大小将为 110,第二个单元格大小将为 220

它将以相同的结构重复以获取更多数据

我可以设计为每行 3 个单元格,但对于休息,我需要帮助

  func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 12 * 3) / 3
    let height = width * 1.5
    return CGSize(width: width, height: height)
}
ios uicollectionview uicollectionviewcell uicollectionviewcompositionallayout uicollectionviewflowlayout
1个回答
0
投票

一种方法是实施

sizeForItemAt

您可以使用模运算符 (

%
) 来确定该行应该有 2 个还是 3 个单元格,如下所示:

let itemsPerRow: CGFloat = indexPath.item % 5 < 3 ? 3 : 2

这将为您提供 3-2-3-2-3... 模式。

这是一个简单的例子...

我们将使用这个单元类 - 单个标签,在所有四个边上都约束 8 个点:

class SomeCell: UICollectionViewCell {
    let theLabel: UILabel = {
        let v = UILabel()
        v.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        v.textAlignment = .center
        v.font = .systemFont(ofSize: 24.0, weight: .regular)
        return v
    }()
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        theLabel.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(theLabel)
        let g = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            theLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            theLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
            theLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
            theLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
        ])
    }
}

然后这个视图控制器类:

class ThreeTwoViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let fl = UICollectionViewFlowLayout()
        fl.scrollDirection = .vertical
        fl.minimumLineSpacing = 12.0
        fl.minimumInteritemSpacing = 0.0
        fl.sectionInset = .init(top: 8.0, left: 8.0, bottom: 8.0, right: 8.0)
        
        let cv = UICollectionView(frame: .zero, collectionViewLayout: fl)
        cv.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(cv)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            cv.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            cv.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            cv.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            cv.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
        ])

        cv.register(SomeCell.self, forCellWithReuseIdentifier: "c")
        cv.dataSource = self
        cv.delegate = self
        
        cv.backgroundColor = .systemYellow
    }
}

extension ThreeTwoViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 30
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "c", for: indexPath) as! SomeCell
        cell.backgroundColor = .systemBlue
        cell.theLabel.text = "\(indexPath.item)"
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        let itemsPerRow: CGFloat = indexPath.item % 5 < 3 ? 3 : 2
        
        var sidePadding: CGFloat = 0.0
        var itemPadding: CGFloat = 12.0
        
        if let fl = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            sidePadding = fl.sectionInset.left + fl.sectionInset.right
            if itemPadding < fl.minimumInteritemSpacing {
                itemPadding = fl.minimumInteritemSpacing
            }
        }
        
        let paddingSpace: CGFloat = itemPadding * (itemsPerRow - 1) + sidePadding
        let availableWidth: CGFloat = collectionView.frame.width - paddingSpace
        let widthPerItem: CGFloat = availableWidth / itemsPerRow
        
        let cellHeight: CGFloat = widthPerItem * 1.5

        return CGSize(width: widthPerItem, height: cellHeight)
    }
    
}

这给了我们这个输出:

© www.soinside.com 2019 - 2024. All rights reserved.