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

如何实现自定义ViewControllerCell的展开收缩:高度翻倍且内容不调整

实现单元格翻倍高度展开且下方单元格下移的方案

1. 维护单元格展开状态(规避复用问题)

UITableViewCell存在复用机制,不能将展开状态存在cell内部,需在ViewController中统一维护每个单元格的状态:

class YourViewController: UIViewController {
    // 单组列表用数组存储状态,多组可改用[IndexPath: Bool]字典
    private var expandedStates: [Bool] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 假设yourDataSource是你的数据源数组,初始化所有单元格为折叠状态
        expandedStates = Array(repeating: false, count: yourDataSource.count)
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 100 // 替换为你的cell默认高度
    }
}

2. 修改选中事件,切换状态并刷新行高

在单元格选中时切换对应位置的展开状态,触发tableView重新计算该行高度:

extension YourViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // 切换当前单元格的展开状态
        expandedStates[indexPath.row] = !expandedStates[indexPath.row]
        // 刷新该行,让tableView重新计算高度
        tableView.reloadRows(at: [indexPath], with: .automatic)
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

3. 固定单元格内部内容,避免随高度调整

确保ViewControllerCell的子视图约束固定位置与高度,不随cell高度变化拉伸:

class ViewControllerCell: UITableViewCell {
    private let titleLabel = UILabel()
    private let contentStackView = UIStackView()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupSubviews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupSubviews() {
        contentView.addSubview(titleLabel)
        contentView.addSubview(contentStackView)
        
        titleLabel.snp.makeConstraints { make in
            make.top.left.right.equalToSuperview().inset(16)
            make.height.equalTo(20) // 固定高度,不随cell变化
        }
        
        contentStackView.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(8)
            make.left.right.equalToSuperview().inset(16)
            make.height.equalTo(40) // 固定高度
            // 注意:不要设置bottom.equalToSuperview(),新增的cell高度会成为空白区域
        }
    }
}

4. 动态返回单元格高度

在数据源代理方法中,根据展开状态返回对应高度:

extension YourViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return yourDataSource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "ViewControllerCell", for: indexPath) as? ViewControllerCell else {
            return UITableViewCell()
        }
        // 配置cell内容
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let defaultHeight: CGFloat = 100 // 替换为你的cell默认高度
        return expandedStates[indexPath.row] ? defaultHeight * 2 : defaultHeight
    }
}

核心要点

  • 状态维护在数据源层:避免cell复用导致的状态混乱
  • 内容固定约束:子视图不绑定cell底部,确保高度增加时内容位置不变
  • 刷新行高:通过reloadRows触发高度重计算,下方单元格会自动下移

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:43:14