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

嵌套UICollectionView父Cell无法根据子内容自适应高度求助

嵌套UICollectionView父Cell无法自适应高度问题

我使用了两层嵌套的UICollectionView,将ChildCollectionView添加至ParentCollectionViewCell中,ChildCollectionView包含3个Cell,但ParentCollectionViewCell无法根据内容自动调整自身框架尺寸。


相关代码

ParentCollectionView

class ViewController: UIViewController {
    
    var parentCollectionView: UICollectionView = {
        let _collectionView = UICollectionView.init(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout.init())
        return _collectionView
    }()
    
    let id = "ParentCollectionViewCell"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(parentCollectionView)
        
        parentCollectionView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            parentCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            parentCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            parentCollectionView.topAnchor.constraint(equalTo: view.topAnchor),
            parentCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        parentCollectionView.dataSource = self
        
        parentCollectionView.register(UINib(nibName: id, bundle: nil), forCellWithReuseIdentifier: id)
        
        if let flowLayout = parentCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        }
    }

}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        1
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: id, for: indexPath) as! ParentCollectionViewCell
        
        cell.backgroundColor = .red
        
        return cell
        
    }
    
}

ParentCollectionViewCell

class ParentCollectionViewCell: UICollectionViewCell {

    var childCollectionView: UICollectionView = {
        let _collectionView = UICollectionView.init(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout.init())
        return _collectionView
    }()
    
    let reuseId = "ChildCollectionViewCell"
    
    private let data = ["ChildCell1","ChildCell2","ChildCell3"]

    override func awakeFromNib() {
        super.awakeFromNib()
        setupViews()
    }
    
    func setupViews() {
        contentView.addSubview(childCollectionView)

        childCollectionView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            childCollectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            childCollectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            childCollectionView.topAnchor.constraint(equalTo: contentView.topAnchor),
            childCollectionView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            childCollectionView.widthAnchor.constraint(equalToConstant: 360)
        ])

        childCollectionView.dataSource = self
        
        childCollectionView.register(UINib(nibName: reuseId, bundle: nil), forCellWithReuseIdentifier: reuseId)
        
        if let flowLayout = childCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        }
    }
}

extension ParentCollectionViewCell: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        data.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseId, for: indexPath) as! ChildCollectionViewCell
        
        cell.backgroundColor = .gray
        
        cell.setupViews()
        
        return cell
    }
}

ChildCollectionViewCell

class ChildCollectionViewCell: UICollectionViewCell {
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    func setupViews() {
        
        let label = UILabel()
        
        label.text = "Child Collection"
        
        label.numberOfLines = 0
        
        label.font = label.font.withSize(50)
        
        contentView.addSubview(label)
        
        label.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            label.topAnchor.constraint(equalTo: contentView.topAnchor),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
        
    }

}

问题原因及解决方案

核心问题

  1. 子CollectionView未明确垂直布局方向,且允许滚动导致内容高度无法完全展开
  2. 子CollectionView被设置固定宽度约束,限制了自适应父Cell宽度的能力
  3. 子Cell重复创建Label,导致布局叠加混乱

具体修改步骤

1. 配置子CollectionView为垂直无滚动布局

在ParentCollectionViewCell的setupViews方法中,修改子CollectionView的布局设置:

if let flowLayout = childCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.scrollDirection = .vertical // 明确垂直布局
    flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    childCollectionView.isScrollEnabled = false // 禁用滚动,让内容全部展开
}

2. 移除子CollectionView的固定宽度约束

删除NSLayoutConstraint.activate数组中的这一行:

// childCollectionView.widthAnchor.constraint(equalToConstant: 360)

3. 修复子Cell重复创建Label的问题

将Label改为Cell的属性,仅初始化一次:

class ChildCollectionViewCell: UICollectionViewCell {
    private let label = UILabel()
    
    override func awakeFromNib() {
        super.awakeFromNib()
        setupViews()
    }
    
    func setupViews() {
        label.text = "Child Collection"
        label.numberOfLines = 0
        label.font = label.font.withSize(50)
        
        contentView.addSubview(label)
        
        label.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            label.topAnchor.constraint(equalTo: contentView.topAnchor),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
    }
}

4. 强制子CollectionView完成布局计算

在ParentCollectionViewCell的setupViews末尾添加:

childCollectionView.reloadData()
childCollectionView.layoutIfNeeded()

修改后效果

ParentCollectionViewCell会根据ChildCollectionView的全部内容高度自动调整自身尺寸,完全包裹3个子Cell,实现预期的垂直展开效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:55:18