静态TableView单元格内嵌动态TableView,如何实现自适应完整显示?
嘿,这个需求我之前处理过好几次,给你一套靠谱的方案,一步步来就行:
内嵌非滚动动态TableView的自动适配方案
1. 先关滚动,避免冲突
首先得把内嵌TableView的滚动功能关掉,不然内容会被截断,还可能和父TableView的滚动逻辑打架:
- 代码里直接设置:
innerTableView.isScrollEnabled = false - 用Storyboard/XIB的话,找到内嵌TableView,取消勾选「Scroll Enabled」选项就行
2. 让内嵌TableView自动算出自身高度
要一次性显示全部内容,核心就是让内嵌TableView的高度等于它的contentSize.height,这里有两种实用方式:
方式一:自定义自动适配的TableView子类(推荐复用)
写个子类封装逻辑,以后用到类似需求直接拿过来用:
class AutoSizingTableView: UITableView { override var contentSize: CGSize { didSet { invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { layoutIfNeeded() return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height) } }
把原来的内嵌TableView换成这个子类,它会自动根据内容高度更新自身的固有尺寸。
方式二:手动监听contentSize变化(快速实现)
不想写子类的话,就在父单元格里加个监听:
// 单元格初始化/awakeFromNib里加监听 innerTableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil) // 实现监听回调 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "contentSize" && object as? UITableView == innerTableView { innerTableView.invalidateIntrinsicContentSize() // 通知父TableView更新布局 self.superview?.superview?.layoutIfNeeded() } } // 记得在销毁时移除监听 deinit { innerTableView.removeObserver(self, forKeyPath: "contentSize") }
3. 给父单元格和TableView设好自动布局
这一步是让父单元格能跟着内嵌TableView自动变高:
- 给内嵌TableView加顶部、底部、左、右四个约束,和父单元格的
contentView边缘对齐(可以根据UI需求留间距) - 给父TableView开启自动行高:
// 在父ViewController里设置 parentTableView.rowHeight = UITableView.automaticDimension parentTableView.estimatedRowHeight = 200 // 设个合理的预估高度,帮助TableView快速计算
4. 异步数据加载后的特殊处理
如果内嵌TableView的数据源是异步获取的,数据刷新后要手动触发一次高度计算:
// 数据源更新后调用 innerTableView.reloadData() // 强制计算内容尺寸并更新布局 innerTableView.layoutIfNeeded() // 通知父TableView刷新对应行 parentTableView.reloadRows(at: [IndexPath(row: yourTargetRow, section: yourTargetSection)], with: .automatic)
5. 踩坑提醒
- 绝对不要给内嵌TableView加固定高度约束,不然会覆盖自动计算的高度
- 自定义单元格要确保
contentView的约束是完整的,别留歧义 - 如果遇到高度计算不准的情况,可以在
viewDidLayoutSubviews里再调用一次innerTableView.invalidateIntrinsicContentSize()
内容的提问来源于stack exchange,提问作者Henrique Mazer
相关产品推荐
相关产品推荐

