如何在tableViewCell中自适应collectionView高度并实现cell自动换行
最优实现方案
核心原理
让CollectionView通过intrinsicContentSize把自身内容高度暴露给AutoLayout,再配合TableView的自动行高能力实现联动适配,不需要手动计算任何高度数值。
具体实现步骤
第一步:自定义自动高度CollectionView
重写contentSize监听和固有尺寸属性,同时禁用滚动:class AutoHeightCollectionView: UICollectionView { override var contentSize: CGSize { didSet { // 内容尺寸变化时通知AutoLayout重新计算固有尺寸 invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { layoutIfNeeded() // 宽度自适应父视图,高度返回内容实际高度 return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height) } override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { super.init(frame: frame, collectionViewLayout: layout) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { isScrollEnabled = false showsVerticalScrollIndicator = false showsHorizontalScrollIndicator = false } }第二步:配置流式布局实现自动换行
使用系统原生UICollectionViewFlowLayout,开启自动尺寸计算:let layout = UICollectionViewFlowLayout() // 开启cell自动尺寸计算 layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize layout.minimumInteritemSpacing = 8 // 同一行cell之间的水平间距 layout.minimumLineSpacing = 8 // 上下行之间的垂直间距 layout.sectionInset = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16) // 整体内边距 let collectionView = AutoHeightCollectionView(collectionViewLayout: layout)注意CollectionViewCell内部约束要完整,比如内部标签的上下左右边距约束要写全,不要给cell添加固定宽高,系统会自动计算cell尺寸。
第三步:配置TableView自动行高
开启TableView的自动高度计算能力:tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 60 // 给一个接近实际效果的预估高度即可TableViewCell内的CollectionView约束要设置为上下左右紧贴cell的contentView,不要添加固定高度约束。
第四步:数据更新时触发高度刷新
每次CollectionView数据源变更调用reloadData()后,主动触发TableView行高刷新:collectionView.reloadData() collectionView.layoutIfNeeded() // 触发TableView重新计算行高,不会全量刷新列表 tableView.beginUpdates() tableView.endUpdates()
参考效果截图



常见问题排查
- 如果出现高度计算错误,检查是否给CollectionView添加了固定高度约束,是否禁用了CollectionView的滚动
- 如果cell无法换行,检查
estimatedItemSize是否设置为自动,cell的最大宽度是否超过了CollectionView的可用宽度 - 如果TableView行高没有同步更新,检查是否在CollectionView数据刷新后调用了TableView的
beginUpdates()和endUpdates()触发重算
内容的提问来源于stack exchange,提问作者brandon lee
相关产品推荐
相关产品推荐

