以编程方式创建扩展的UItableViewCell

我有一个tableviewcell,我想扩展和折叠。 我发现的所有示例都是Storyboard基础,我正在尝试以编程方式执行此操作。 我最初的想法是创建一个子视图并将其约束到内容视图,但是当我使用heightForRowAt调整单元格的高度时,它也会增加内容视图的大小(这是有意义的)。 关于我应该怎么做的任何想法?

对于视觉参考,这是我想要发生的事情 在此处输入图像描述

使用垂直UIStackView ,底部视图isHidden设置为true,然后点击(或任何扩展的触发器)只需更改isHidden = false 。 考虑到UIStackView如何处理isHidden ,我想这将是最简单的。 另一种方法是设置自动布局约束,并通过将NSLayoutConstraint的常量设置为0来更改底部视图的高度锚点。

无论如何,无论你选择哪个appraoch,你都必须告诉tableView刷新它的显示(来自viewcontroller):

 func refreshTableAfterCellExpansion() { self.tableView.beginUpdates() self.tableView.setNeedsDisplay() self.tableView.endUpdates() } 

例如,检查以下问题及其答案 。

使用playground的示例(带有UIStackView ,另一个使用相同的原理):

 import UIKit import PlaygroundSupport class ExpandableCellViewController: UITableViewController, ExpandableCellDelegate { override func loadView() { super.loadView() tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 44 tableView.register(ExpandableCell.self, forCellReuseIdentifier: "expandableCell") } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "expandableCell", for: indexPath) as! ExpandableCell cell.delegate = self return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell { cell.isExpanded = true } } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { if let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell { cell.isExpanded = false } } func expandableCellLayoutChanged(_ expandableCell: ExpandableCell) { refreshTableAfterCellExpansion() } func refreshTableAfterCellExpansion() { self.tableView.beginUpdates() self.tableView.setNeedsDisplay() self.tableView.endUpdates() } } protocol ExpandableCellDelegate: class { func expandableCellLayoutChanged(_ expandableCell: ExpandableCell) } class ExpandableCell: UITableViewCell { weak var delegate: ExpandableCellDelegate? fileprivate let stack = UIStackView() fileprivate let topView = UIView() fileprivate let bottomView = UIView() var isExpanded: Bool = false { didSet { bottomView.isHidden = !isExpanded delegate?.expandableCellLayoutChanged(self) } } override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) selectionStyle = .none contentView.addSubview(stack) stack.addArrangedSubview(topView) stack.addArrangedSubview(bottomView) stack.translatesAutoresizingMaskIntoConstraints = false topView.translatesAutoresizingMaskIntoConstraints = false bottomView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ stack.topAnchor.constraint(equalTo: contentView.topAnchor), stack.leftAnchor.constraint(equalTo: contentView.leftAnchor), stack.rightAnchor.constraint(equalTo: contentView.rightAnchor), stack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), topView.heightAnchor.constraint(equalToConstant: 50), bottomView.heightAnchor.constraint(equalToConstant: 30), ]) stack.axis = .vertical stack.distribution = .fill stack.alignment = .fill stack.spacing = 0 topView.backgroundColor = .red bottomView.backgroundColor = .blue bottomView.isHidden = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } // Present the view controller in the Live View window PlaygroundPage.current.liveView = ExpandableCellViewController() 

我只想定义2个单元格类型,并选择适合tableView的那个(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)

您可以使用标志来指示是否展开特定的部分或行,并在UITableView上使用此方法:

  reloadRows() reloadSections() 

并根据标志更改heightForRow方法返回所需高度。 如果您希望一次扩展多行,则可以对数据源中的每个项使用ViewModel,并在调用didSelectItemAt或didDeselectItemAt方法时更新其中的标志,然后使用所需的动画重新加载行或节。