使用UIStackViewdynamicUITableView行高度?

惊讶这不是开箱即用,因为这似乎是堆栈视图的重要用例。 我有一个UITableViewCell子类添加一个UIStackView到contentView。 我将标签添加到tableView(_cellForRowAtIndexPath:)的堆栈视图中,tableview被设置为使用dynamic行高,但至less在Xcode 7.3中看起来不起作用。 我还有一个印象,就是在堆栈视图中隐藏排列的子视图是可以animation的,但是这似乎也被打破了。

任何想法如何让这个工作正常?

破碎的动态行高

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

看起来,为了这个工作,约束需要被添加到UITableViewCell的init中,并添加到contentView而不是单元格的视图。

在这里输入图像说明

工作代码如下所示:

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