UICollectionViewCell 的动态高度以编程方式与约束?

Posted

技术标签:

【中文标题】UICollectionViewCell 的动态高度以编程方式与约束?【英文标题】:Dynamic height of UICollectionViewCell programmatically with constraints? 【发布时间】:2017-10-23 21:05:13 【问题描述】:

我从来没有见过有这么多不同答案的主题,而不是为集合视图单元格设置动态高度。一些解决方案具有难以想象的代码量,这只会进一步促成UICollectionView 是一个集群的共识,因为这可以通过UITableView 实现而无需做任何事情,因为当约束被正确链接时,动态单元高度是内置的.但我想更好地处理集合视图。这是一场噩梦。

如何在没有一百行代码的情况下在 Swift 中以编程方式(无情节提要)将集合视图单元格的高度设置为动态的内容大小?

您可以将以下内容插入一个空白项目,如果您愿意,它将运行干净。

CollectionViewFlowLayout:

class CollectionViewFlowLayout: UICollectionViewFlowLayout 

    // inits
    override init() 
        super.init()

        config()
    

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

    // config
    func config() 
        scrollDirection = .vertical
        minimumLineSpacing = 0
        minimumInteritemSpacing = 0
    

CollectionViewController

class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout 

    // model properties
    let colorArray: [UIColor] = [.red, .green, .blue, .yellow]
    let labelArray: [String] = [
        "sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf",
        "sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf",
        "sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf",
        "sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf sconewolf"
    ]

    // view did load
    override func viewDidLoad() 
        super.viewDidLoad()

        config()
    

    // config
    func config() 
        collectionView?.dataSource = self
        collectionView?.delegate = self
        collectionView?.backgroundColor = UIColor.gray
        collectionView?.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0)
        collectionView?.alwaysBounceVertical = true
        collectionView?.alwaysBounceHorizontal = false
        collectionView?.register(CollectionViewCell.self, forCellWithReuseIdentifier: "cell1")
    

    // data source: number of items in section
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return colorArray.count
    

    // data source: cell for item
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath) as! CollectionViewCell
        cell.backgroundColor = colorArray[indexPath.item]
        cell.label.text = labelArray[indexPath.item]
        return cell
    

    // delegate: size for item
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 

        return CGSize(width: view.frame.width, height: 200)
    

CollectionViewCell

class CollectionViewCell: UICollectionViewCell 

    // view properties
    var label = UILabel()

    // inits
    override init(frame: CGRect) 
        super.init(frame: frame)

        config()
        addLabel()
    

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

    // config
    func config() 
        self.translatesAutoresizingMaskIntoConstraints = false
    

    // add label
    func addLabel() 
        label.font = UIFont.boldSystemFont(ofSize: 18)
        label.textColor = UIColor.black
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        label.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        label.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        label.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        label.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        label.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        label.sizeToFit()
    

【问题讨论】:

【参考方案1】:

在this 帖子的帮助下,我能够以编程方式创建动态 UICollectionViewCell:

设置 UICollectionView 布局的estimatedItemSize 如下:

if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout 
    flowLayout.estimatedItemSize = CGSize(width: 1, height: 1)

在 UICollectionViewCell 的 contentView 中添加你的 UIControls

self.contentView.translatesAutoresizingMaskIntoConstraints = false

let screenWidth = UIScreen.main.bounds.size.width

contentView.addSubview(msgLabel)

[
    msgLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
    msgLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
    msgLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
    msgLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
    msgLabel.widthAnchor.constraint(equalToConstant: screenWidth - 16)
    ].forEach $0.isActive = true 

设置UILabel的numberOfLines为0

【讨论】:

以上是关于UICollectionViewCell 的动态高度以编程方式与约束?的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewCell 中的动态高度 noScrollable UICollectionView

动态调整 UICollectionViewCell 的大小

使用图像上传 Swift 动态调整 UICollectionViewCell 的大小

具有动态大小单元格间距问题的 UICollectionViewCell

iOS - UICollectionViewCell 的动态大小宽度

UICollectionViewCell 宽度的动态变化