You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift类中无Storyboard编程实现带自定义单元格的UICollectionView

纯代码实现带自定义标签单元格的UICollectionView(Swift)

我来帮你完善这个纯代码创建UICollectionView的实现,确保能正常显示带标签的自定义单元格,下面是完整的可运行代码和关键步骤解析:

完整实现代码

首先我们需要创建一个自定义UICollectionViewCell,把标签封装在单元格内部(避免复用混乱),再实现承载CollectionView的BoardView:

import UIKit

// 自定义带标签的CollectionView单元格
class CustomCollectionViewCell: UICollectionViewCell {
    // 单元格内的标签
    let cellLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 16)
        label.translatesAutoresizingMaskIntoConstraints = false // 关闭自动布局转换
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupCellUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented") // 纯代码实现无需支持Storyboard/XIB
    }
    
    private func setupCellUI() {
        // 把标签添加到单元格的contentView(必须用contentView,不能直接加在cell上)
        contentView.addSubview(cellLabel)
        // 设置标签的AutoLayout约束
        NSLayoutConstraint.activate([
            cellLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            cellLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            cellLabel.leadingAnchor.constraint(greaterThanOrEqualTo: contentView.leadingAnchor, constant: 8),
            cellLabel.trailingAnchor.constraint(lessThanOrEqualTo: contentView.trailingAnchor, constant: -8)
        ])
        // 给单元格加一点样式
        contentView.backgroundColor = .lightGray
        contentView.layer.cornerRadius = 8
    }
}

// 承载CollectionView的自定义View
class BoardView: UIView, UICollectionViewDataSource, UICollectionViewDelegate {
    var boardTable: UICollectionView!
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] // 测试数据
    
    // 便利初始化方法
    convenience init(frame: CGRect, title: String) {
        self.init(frame: frame)
        // 如果需要用title做额外操作(比如设置视图标题),可以在这里添加逻辑
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupCollectionView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupCollectionView()
    }
    
    private func setupCollectionView() {
        // 1. 配置CollectionView布局
        layout.scrollDirection = .vertical // 垂直滚动
        layout.itemSize = CGSize(width: 80, height: 80) // 单元格大小
        layout.minimumInteritemSpacing = 10 // 单元格水平间距
        layout.minimumLineSpacing = 10 // 单元格垂直间距
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) // 整体内边距
        
        // 2. 初始化CollectionView
        boardTable = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
        boardTable.translatesAutoresizingMaskIntoConstraints = false
        boardTable.dataSource = self
        boardTable.delegate = self
        boardTable.backgroundColor = .white
        
        // 3. 注册自定义单元格(必须注册,否则无法复用)
        boardTable.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: "CustomCell")
        
        // 4. 添加到父视图并设置约束(让CollectionView铺满整个BoardView)
        self.addSubview(boardTable)
        NSLayoutConstraint.activate([
            boardTable.topAnchor.constraint(equalTo: self.topAnchor),
            boardTable.leadingAnchor.constraint(equalTo: self.leadingAnchor),
            boardTable.trailingAnchor.constraint(equalTo: self.trailingAnchor),
            boardTable.bottomAnchor.constraint(equalTo: self.bottomAnchor)
        ])
    }
    
    // MARK: - UICollectionViewDataSource 数据源方法
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count // 返回数据总数
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        // 复用单元格并强转为自定义类型
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCollectionViewCell
        // 给单元格的标签赋值
        cell.cellLabel.text = items[indexPath.item]
        return cell
    }
    
    // MARK: - UICollectionViewDelegate 可选代理方法(点击事件)
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("点击了第\(indexPath.item + 1)个单元格,内容:\(items[indexPath.item])")
    }
}

关键要点说明

  • 自定义单元格的必要性:把UILabel封装在单元格内部,而不是放在BoardView中,这样每个单元格都有独立的标签,避免复用时出现内容混乱的问题。
  • 布局配置:通过UICollectionViewFlowLayout可以灵活控制单元格的大小、间距、滚动方向,适配不同的UI需求。
  • AutoLayout约束:所有视图都关闭了translatesAutoresizingMaskIntoConstraints,使用代码约束确保在不同屏幕尺寸下都能正常显示。
  • 单元格注册与复用:必须先注册自定义单元格类,再通过dequeueReusableCell复用,这是CollectionView性能优化的核心。

内容的提问来源于stack exchange,提问作者JoLight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:28:21