如何基于UITableViewCell内部的UICollectionViewCell动态设置UITableViewCell高度
动态调整嵌套CollectionView的TableViewCell高度方案
核心逻辑
让外层UITableView自动感知内部UICollectionView的内容高度,不需要手动写死cell高度,整套逻辑兼容流布局、自定义布局等所有合法的UICollectionView布局。
步骤1:配置CollectionView约束
- 给嵌套在UITableViewCell.contentView中的UICollectionView添加上、下、左、右四个边距约束到父视图,不要手动设置固定的height约束
- 确保UICollectionView的宽度是固定的(和cell宽度绑定即可),这样布局计算出来的contentSize高度才会准确
- 如果你用的是自定义UICollectionViewLayout,需要确保
collectionViewContentSize属性返回的内容尺寸是正确的
小提示:如果你的CollectionView是横向滚动的,不需要适配动态高度,直接写死height约束即可,不需要走后续逻辑。
步骤2:监听CollectionView内容尺寸变化
通过KVO监听UICollectionView的contentSize属性,内容尺寸变化时通知外层刷新行高:
// 自定义UITableViewCell类内部 class CustomTableViewCell: UITableViewCell { // 高度更新回调,用于通知外层TableView var onHeightUpdate: (() -> Void)? private var contentSizeObservation: NSKeyValueObservation? let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupUI() // 这里实现CollectionView的添加、约束配置、代理数据源绑定 // 监听contentSize变化 contentSizeObservation = collectionView.observe(\.contentSize, options: [.new]) { [weak self] _, change in guard let self = self, let newHeight = change.newValue?.height else { return } // 加个判断,只有高度真的变了才触发回调,避免重复刷新 if self.collectionView.bounds.height != newHeight { self.onHeightUpdate?() } } } }
如果使用Objective-C实现,逻辑完全一致,替换为OC的KVO写法即可。
步骤3:外层UITableView配置自动行高
// 初始化UITableView时配置 tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 100 // 填写接近你业务场景的预估高度即可,不要求完全准确 // cellForRowAt中绑定回调 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellID", for: indexPath) as! CustomTableViewCell // 给内部CollectionView赋值对应行的数据源 cell.collectionViewDataSource = yourDataList[indexPath.row] // 绑定高度更新回调 cell.onHeightUpdate = { [weak self] in guard let self = self else { return } // 触发TableView重新计算行高,不会全量刷新,性能损耗极低 tableView.performBatchUpdates(nil) } return cell }
可选优化方案(适合数据源固定场景)
如果你的CollectionView数据源是固定不变的,可以提前计算好每一行CollectionView的内容高度,直接在tableView(_:heightForRowAt:)代理方法中返回预计算的高度,性能比KVO监听方案更好,适合列表数据量大的场景。
内容的提问来源于stack exchange,提问作者Charlie
相关产品推荐
相关产品推荐

