You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TableView控制器中如何点击DefaultCell调用ExpansionCell?

点击DefaultCell调用ExpansionCell的实现方案

嘿,这个需求在TableView开发里挺常见的,我给你两种实用的实现思路,你可以根据自己的业务场景来选:

方案一:动态修改数据源,插入/删除ExpansionCell

这种方式是通过维护一个包含单元格类型和状态的数据源,点击DefaultCell时切换展开状态,然后在对应的位置插入或移除ExpansionCell,适合ExpansionCell作为独立行的场景。

步骤1:定义数据模型

首先我们需要一个能标记单元格类型和展开状态的模型,用来管理数据源:

// 定义单元格类型
enum CellType {
    case defaultCell(data: YourDefaultDataModel) // 替换成你实际的DefaultCell数据模型
    case expansionCell(data: YourExpansionDataModel) // 替换成你实际的ExpansionCell数据模型
}

// 每个列表项的结构,包含类型和展开状态(仅针对DefaultCell)
struct CellListItem {
    var type: CellType
    var isExpanded: Bool = false
}

步骤2:配置TableView数据源

在你的TableViewController里,用上面的模型数组作为数据源,实现基本的数据源方法:

var cellItems: [CellListItem] = [] // 初始化时填充你的DefaultCell数据

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return cellItems.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let item = cellItems[indexPath.row]
    
    switch item.type {
    case .defaultCell(let data):
        let cell = tableView.dequeueReusableCell(withIdentifier: "DefaultCell", for: indexPath) as! DefaultCell
        cell.configure(with: data) // 调用你自己的配置方法填充数据
        return cell
        
    case .expansionCell(let data):
        let cell = tableView.dequeueReusableCell(withIdentifier: "ExpansionCell", for: indexPath) as! ExpansionCell
        cell.configure(with: data) // 同理配置ExpansionCell数据
        return cell
    }
}

步骤3:处理点击事件

在didSelectRowAt方法里,判断点击的是DefaultCell,然后切换展开状态,插入或删除ExpansionCell:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    let currentItem = cellItems[indexPath.row]
    
    // 只处理DefaultCell的点击
    guard case .defaultCell = currentItem.type else { return }
    
    // 切换展开状态
    var updatedItem = currentItem
    updatedItem.isExpanded = !updatedItem.isExpanded
    cellItems[indexPath.row] = updatedItem
    
    // 根据状态更新数据源和表格
    if updatedItem.isExpanded {
        // 准备ExpansionCell的数据,替换成你实际的数据源
        let expansionData = YourExpansionDataModel(...)
        let expansionItem = CellListItem(type: .expansionCell(data: expansionData), isExpanded: false)
        cellItems.insert(expansionItem, at: indexPath.row + 1)
        
        // 插入行的动画效果
        tableView.insertRows(at: [IndexPath(row: indexPath.row + 1, section: indexPath.section)], with: .automatic)
    } else {
        // 删除对应的ExpansionCell
        cellItems.remove(at: indexPath.row + 1)
        tableView.deleteRows(at: [IndexPath(row: indexPath.row + 1, section: indexPath.section)], with: .automatic)
    }
}

方案二:将ExpansionCell嵌套进DefaultCell,实现折叠展开

如果你的ExpansionCell不需要作为独立行,而是DefaultCell的展开内容,那可以把它嵌套进DefaultCell里,通过控制单元格高度来实现展开收起。

步骤1:改造DefaultCell

在DefaultCell内部添加ExpansionCell作为子视图,通过约束控制它的显示/隐藏:

class DefaultCell: UITableViewCell {
    private var expansionHeightConstraint: NSLayoutConstraint!
    var isExpanded: Bool = false {
        didSet {
            // 切换展开状态时,修改高度约束并添加动画
            expansionHeightConstraint.constant = isExpanded ? 120 : 0 // 120替换成ExpansionCell的实际高度
            UIView.animate(withDuration: 0.3) {
                self.layoutIfNeeded()
            }
        }
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupExpansionCell()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupExpansionCell()
    }
    
    private func setupExpansionCell() {
        // 初始化ExpansionCell
        let expansionCell = ExpansionCell(style: .default, reuseIdentifier: "ExpansionCell")
        expansionCell.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(expansionCell)
        
        // 设置约束:左右对齐,顶部接DefaultCell内容底部,底部接cell底部,高度默认0
        expansionHeightConstraint = expansionCell.heightAnchor.constraint(equalToConstant: 0)
        NSLayoutConstraint.activate([
            expansionCell.topAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 8),
            expansionCell.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
            expansionCell.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
            expansionHeightConstraint,
            expansionCell.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8)
        ])
    }
    
    // 配置DefaultCell的主内容
    func configure(with data: YourDefaultDataModel) {
        // 填充你的DefaultCell数据,比如设置textLabel的文本等
    }
}

步骤2:处理TableView点击和行高

在TableViewController里,点击DefaultCell时切换它的展开状态,并刷新行高:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    
    guard let defaultCell = tableView.cellForRow(at: indexPath) as? DefaultCell else { return }
    defaultCell.isExpanded = !defaultCell.isExpanded
    
    // 刷新行高,让TableView重新计算单元格高度
    tableView.beginUpdates()
    tableView.endUpdates()
}

// 动态计算单元格高度
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if let cell = tableView.cellForRow(at: indexPath) as? DefaultCell {
        let defaultBaseHeight: CGFloat = 60 // DefaultCell未展开时的基础高度
        return defaultBaseHeight + (cell.isExpanded ? 136 : 0) // 136是ExpansionCell高度+上下间距
    }
    return UITableView.automaticDimension
}

注意事项

  • 记得在viewDidLoad里注册两个单元格的标识符:tableView.register(DefaultCell.self, forCellReuseIdentifier: "DefaultCell"),ExpansionCell同理。
  • 代码里的模型类、高度值都要根据你的实际UI和业务逻辑调整。

内容的提问来源于stack exchange,提问作者goga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:40:56