Swift iOS:实现单元格内嵌非滚动自适应高度表格
实现外层表格内嵌自适应高度子表格的完整方案
刚好做过类似的需求,给你一套完整的实现方案,完全匹配你要的外层表格每个单元格内嵌不可滚动、自适应高度子表格的效果:
整体架构梳理
- 外层表格:由
ViewController管理,数据源是硬编码的食物组数组 - 外层单元格:
FoodGroupCell,每个单元格包含一个标题标签和一个子表格 - 子表格单元格:
FoodItemCell,负责展示单个食物项
1. ViewController 核心代码
import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // 硬编码的食物组数据源 let foodGroups = [ FoodGroup(name: "水果", items: ["苹果", "香蕉", "草莓"]), FoodGroup(name: "蔬菜", items: ["胡萝卜", "西兰花", "菠菜"]), FoodGroup(name: "主食", items: ["米饭", "面包", "面条"]) ] @IBOutlet weak var mainTableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // 注册外层单元格XIB mainTableView.register(UINib(nibName: "FoodGroupCell", bundle: nil), forCellReuseIdentifier: "FoodGroupCell") // 开启外层表格自适应高度 mainTableView.rowHeight = UITableView.automaticDimension mainTableView.estimatedRowHeight = 200 // 给一个初始估算高度,提升渲染性能 } // MARK: - 外层表格数据源&代理 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return foodGroups.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FoodGroupCell", for: indexPath) as! FoodGroupCell let currentGroup = foodGroups[indexPath.row] cell.configure(with: currentGroup) return cell } } // 食物组模型 struct FoodGroup { let name: String let items: [String] }
2. FoodGroupCell 实现(XIB + Swift)
XIB布局要点
- 拖入一个
UILabel用于显示食物组名称,设置好上下左右约束 - 拖入一个
UITableView作为子表格,设置上下左右完全贴合单元格内容视图,不要设置固定高度 - 给子表格关联IBOutlet(命名为
itemsTableView),并设置其delegate和dataSource为当前FoodGroupCell
Swift代码实现
import UIKit class FoodGroupCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var groupTitleLabel: UILabel! @IBOutlet weak var itemsTableView: UITableView! private var foodItems: [String] = [] override func awakeFromNib() { super.awakeFromNib() setupSubTableView() } private func setupSubTableView() { // 注册子表格单元格XIB itemsTableView.register(UINib(nibName: "FoodItemCell", bundle: nil), forCellReuseIdentifier: "FoodItemCell") // 关键:禁用子表格滚动,确保它能根据内容自适应高度 itemsTableView.isScrollEnabled = false // 开启子表格自适应高度 itemsTableView.rowHeight = UITableView.automaticDimension itemsTableView.estimatedRowHeight = 44 itemsTableView.dataSource = self itemsTableView.delegate = self } // 配置单元格数据 func configure(with group: FoodGroup) { groupTitleLabel.text = group.name foodItems = group.items itemsTableView.reloadData() // 强制刷新布局,确保外层单元格能正确计算高度 itemsTableView.layoutIfNeeded() self.setNeedsLayout() } // MARK: - 子表格数据源&代理 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return foodItems.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FoodItemCell", for: indexPath) as! FoodItemCell cell.foodNameLabel.text = foodItems[indexPath.row] return cell } }
3. FoodItemCell 实现
XIB布局要点
- 拖入一个
UILabel(命名为foodNameLabel),设置上下左右约束,开启自动换行(numberOfLines设为0)
Swift代码实现
import UIKit class FoodItemCell: UITableViewCell { @IBOutlet weak var foodNameLabel: UILabel! override func awakeFromNib() { super.awakeFromNib() // 确保标签能自适应多行内容 foodNameLabel.numberOfLines = 0 } }
关键注意事项
- 外层表格和子表格都必须设置
rowHeight = UITableView.automaticDimension和estimatedRowHeight,这是自适应高度的核心 - 子表格一定要关闭滚动(
isScrollEnabled = false),否则它会保持固定高度,无法根据内容拉伸 - 在
FoodGroupCell的configure方法中,刷新子表格数据后要强制触发布局刷新,避免外层单元格高度计算错误
内容的提问来源于stack exchange,提问作者bmclachlin
相关产品推荐
相关产品推荐

