ios xcode uitableview autolayout uistackview

ios - ¿Dinámica UITableView altura de fila utilizando UIStackView?



xcode autolayout (1)

Parece que para que esto funcione, las restricciones deben agregarse en el inicio de UITableViewCell y agregarse a contentView lugar de la vista de la celda.

El código de trabajo se ve así:

import UIKit class StackCell : UITableViewCell { enum VisualFormat: String { case HorizontalStackViewFormat = "H:|[stackView]|" case VerticalStackViewFormat = "V:|[stackView(>=44)]|" } var hasSetupConstraints = false lazy var stackView : UIStackView! = { let stack = UIStackView() stack.axis = UILayoutConstraintAxis.Vertical stack.distribution = .FillProportionally stack.alignment = .Fill stack.spacing = 3.0 stack.translatesAutoresizingMaskIntoConstraints = false stack.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical) return stack }() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(stackView) addStackConstraints() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func addStackConstraints() { let viewsDictionary: [String:AnyObject] = ["stackView" : stackView] var newConstraints = [NSLayoutConstraint]() newConstraints += self.newConstraints(VisualFormat.HorizontalStackViewFormat.rawValue, viewsDictionary: viewsDictionary) newConstraints += self.newConstraints(VisualFormat.VerticalStackViewFormat.rawValue, viewsDictionary: viewsDictionary) contentView.addConstraints(newConstraints) super.updateConstraints() } private func newConstraints(visualFormat: String, viewsDictionary: [String:AnyObject]) -> [NSLayoutConstraint] { return NSLayoutConstraint.constraintsWithVisualFormat(visualFormat, options: [], metrics: nil, views: viewsDictionary) } }

Sorprendido, esto no funciona fuera de la caja, ya que parece ser un caso de uso importante para las vistas de pila. Tengo una subclase UITableViewCell que agrega un UIStackView al contentView. Estoy agregando etiquetas a la vista de pila en tableView(_cellForRowAtIndexPath:) y la vista de tabla está configurada para usar alturas de fila dinámicas, pero no parece funcionar, al menos en Xcode 7.3. También tenía la impresión de que ocultar subvistas organizadas en una vista de pila era animable, pero eso también parece estar roto.

¿Alguna idea sobre cómo hacer que esto funcione correctamente?

class StackCell : UITableViewCell { enum VisualFormat: String { case HorizontalStackViewFormat = "H:|[stackView]|" case VerticalStackViewFormat = "V:|[stackView(>=44)]|" } var hasSetupConstraints = false lazy var stackView : UIStackView! = { let stack = UIStackView() stack.axis = .Vertical stack.distribution = .FillProportionally stack.alignment = .Fill stack.spacing = 3.0 stack.translatesAutoresizingMaskIntoConstraints = false return stack }() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(stackView) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func updateConstraints() { if !hasSetupConstraints { hasSetupConstraints = true let viewsDictionary: [String:AnyObject] = ["stackView" : stackView] var newConstraints = [NSLayoutConstraint]() newConstraints += self.newConstraints(VisualFormat.HorizontalStackViewFormat.rawValue, viewsDictionary: viewsDictionary) newConstraints += self.newConstraints(VisualFormat.VerticalStackViewFormat.rawValue, viewsDictionary: viewsDictionary) addConstraints(newConstraints) } super.updateConstraints() } private func newConstraints(visualFormat: String, viewsDictionary: [String:AnyObject]) -> [NSLayoutConstraint] { return NSLayoutConstraint.constraintsWithVisualFormat(visualFormat, options: [], metrics: nil, views: viewsDictionary) } class ViewController: UITableViewController { private let reuseIdentifier = "StackCell" private let cellClass = StackCell.self override func viewDidLoad() { super.viewDidLoad() configureTableView(self.tableView) } private func configureTableView(tableView: UITableView) { tableView.registerClass(cellClass, forCellReuseIdentifier: reuseIdentifier) tableView.separatorStyle = .SingleLine tableView.estimatedRowHeight = 88 tableView.rowHeight = UITableViewAutomaticDimension } private func newLabel(title: String) -> UILabel { let label = UILabel() label.text = title return label } // MARK: - UITableView override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 4 } override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 44.0 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! StackCell cell.stackView.arrangedSubviews.forEach({$0.removeFromSuperview()}) cell.stackView.addArrangedSubview(newLabel("/(indexPath.section)-/(indexPath.row)")) cell.stackView.addArrangedSubview(newLabel("Second Label")) cell.stackView.addArrangedSubview(newLabel("Third Label")) cell.stackView.addArrangedSubview(newLabel("Fourth Label")) cell.stackView.addArrangedSubview(newLabel("Fifth Label")) return cell } override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let cell = tableView.cellForRowAtIndexPath(indexPath) as! StackCell for (idx, view) in cell.stackView.arrangedSubviews.enumerate() { if idx == 0 { continue } view.hidden = !view.hidden } UIView.animateWithDuration(0.3, animations: { cell.contentView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates() }) } }