Crear mediante progtwigción una UItableViewCell en expansión

Tengo una mesa de visión que quiero ampliar y colapsar al tocar. Todos los ejemplos que he encontrado son base Storyboard y estoy tratando de hacer esto programáticamente. Lo que inicialmente pensé fue crear una subvista y restringirla a la vista de contenido, pero cuando ajusto la altura de la celda con heightForRowAt también aumenta el tamaño de la vista de contenido (lo cual tiene sentido). ¿Alguna idea sobre cómo debería hacerlo?

Para referencia visual aquí es lo que quiero que suceda enter image description here

Use UIStackView vertical con la vista inferior isHidden establecido en true, luego al tocar (o lo que sea que desencadene la expansión) simplemente cambie isHidden = false . Creo que eso sería lo más fácil, considerando cómo UIStackView trata con isHidden . Otro enfoque es configurar restricciones de autodiseño y cambiar el ancla de altura de la vista inferior estableciendo la constante de NSLayoutConstraint en 0.

De todos modos, cualquiera que sea el tipo de aplicación que elija, tendrá que indicarle a tableView que actualice su visualización (desde viewcontroller):

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

Por ejemplo, verifique la siguiente pregunta y su respuesta .

Un ejemplo usando juegos infantiles (el que tiene UIStackView , el otro usa el mismo principio):

 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() 

Simplemente definiría 2 tipos de celda y seleccionaría la que sea apropiada en tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)

Puede usar un indicador para indicar si una sección o fila específica está expandida y usar este método en UITableView:

  reloadRows() reloadSections() 

Y cambie el método heightForRow para devolver la altura deseada según el indicador. Si desea poder expandir más de una fila a la vez, puede usar un ViewModel para cada elemento en su fuente de datos y actualizar un indicador cuando se invoquen los métodos didSelectItemAt o didDeselectItemAt y luego volver a cargar la fila o sección con la animación deseada.