嵌套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) ]) } }
问题原因及解决方案
核心问题
- 子CollectionView未明确垂直布局方向,且允许滚动导致内容高度无法完全展开
- 子CollectionView被设置固定宽度约束,限制了自适应父Cell宽度的能力
- 子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
相关产品推荐
相关产品推荐

