2016-03-26 15 views
17

Überrascht funktioniert dies nicht aus der Box, da dies ein wichtiger Anwendungsfall für Stack-Ansichten zu sein scheint. Ich habe eine UITableViewCell Unterklasse, die ein UIStackView zum contentView hinzufügt. Ich füge Labels zur Stack-Ansicht in tableView(_cellForRowAtIndexPath:) hinzu, und die Tabellenansicht ist so eingestellt, dass sie dynamische Zeilenhöhen verwendet, aber zumindest in Xcode 7.3 scheint sie nicht zu funktionieren. Ich hatte auch den Eindruck, dass das Verbergen von arrangierten Subviews in einer Stapelansicht animierbar war, aber das scheint auch gebrochen zu sein.Dynamische UITableView Zeilenhöhe mit UIStackView?

Irgendwelche Ideen, wie man das richtig funktioniert?

Broken dynamic row heights

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

     }) 
    } 
} 

Antwort

16

Es scheint, dass für diese die Einschränkungen in der init der UITableViewCell hinzugefügt werden müssen, arbeiten und zu den contentView stattdessen Blick auf Zelle.

enter image description here

Der Arbeits Code sieht wie folgt aus:

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

Jedes Mal, wenn ich eine Frage stellen, wo ich UIStackViews programmatisch ich schreibe, jeder auf mich hasst. Ich bin froh, dass jemand anderes es macht. Auch danke für die Antwort;) – Trip

+1

@Trip +1 für programmgesteuert – netigger

+0

Ich musste auch 'geschätztRowHeight' auf dem TableView setzen und dann begann es magisch zu arbeiten! – Inti

Verwandte Themen