Dynamic UITableView row height using UIStackView?

memmons

Surprised this isn't working out of the box, as this seems to be an important use case for stack views. I have a UITableViewCell subclass which adds a UIStackView to the contentView. I'm adding labels to the stack view in tableView(_cellForRowAtIndexPath:) and the tableview is set to use dynamic row heights, but it doesn't appear to work, at least in Xcode 7.3. I was also under the impression that hiding arranged subviews in a stack view was animatable, but that seems broken as well.

Any ideas on how to get this working correctly?

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

        })
    }
}
memmons

It seems that for this to work the constraints need to be added in the init of the UITableViewCell and added to the contentView instead of cell's view.

enter image description here

The working code looks like this:

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

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Dynamic row height in UITableView using custom cell from xib

From Dev

Accessing the Row Height in Dynamic UITableView Prototypes

From Dev

UITableView dynamic cell heights - reload height for single row

From Dev

iOS/Swift: Dynamic UITableViewCell row height with embedded UITableView not working

From Dev

Uitableview cell dynamic height

From Dev

Dynamic UITableView height

From Dev

Dynamic height of UITableview Issue

From Dev

iOS 7/8 UITableView Cell: Two UILabels with dynamic height with auto layout for variable row height

From Java

Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

From Dev

UITableView default row height Xcode

From Dev

UITableView deleting row reduced table row height

From Dev

Set row height of a UITableView according to the cell in that row

From Dev

Table with dynamic row height issue

From Dev

Dynamic Row Height and sizeWithAttributes Warning

From Dev

Product list row with dynamic height

From Dev

Table with dynamic row height issue

From Dev

RecyclerView GridLayoutManager and dynamic row height

From Dev

UITableView Using a row as a segue

From Dev

UITableView inside UITableViewCell with dynamic cell height

From Dev

UITableView with 3 custom views and dynamic height

From Dev

How to resize the UITableView row height in Objective C

From Dev

How to set height constraint of UITableView according to dynamic height cells?

From Dev

Set height of UITableView which contain dynamic Cell Height

From Dev

UITableView: automatically set height for the row and fix it with max height constant

From Dev

Dynamic UITableView cell height with AutoLayout with Dynamic Type Labels

From Dev

UIStackView not updating after updating height of subview (UITableView with no scroll) while inside a ScrollView

From Dev

Make multiple links in a row the same dynamic height

From Dev

uicollectionview's dynamic height as per row values

From Dev

UITableViewCell dynamic height breaks after insert row

Related Related

  1. 1

    Dynamic row height in UITableView using custom cell from xib

  2. 2

    Accessing the Row Height in Dynamic UITableView Prototypes

  3. 3

    UITableView dynamic cell heights - reload height for single row

  4. 4

    iOS/Swift: Dynamic UITableViewCell row height with embedded UITableView not working

  5. 5

    Uitableview cell dynamic height

  6. 6

    Dynamic UITableView height

  7. 7

    Dynamic height of UITableview Issue

  8. 8

    iOS 7/8 UITableView Cell: Two UILabels with dynamic height with auto layout for variable row height

  9. 9

    Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

  10. 10

    UITableView default row height Xcode

  11. 11

    UITableView deleting row reduced table row height

  12. 12

    Set row height of a UITableView according to the cell in that row

  13. 13

    Table with dynamic row height issue

  14. 14

    Dynamic Row Height and sizeWithAttributes Warning

  15. 15

    Product list row with dynamic height

  16. 16

    Table with dynamic row height issue

  17. 17

    RecyclerView GridLayoutManager and dynamic row height

  18. 18

    UITableView Using a row as a segue

  19. 19

    UITableView inside UITableViewCell with dynamic cell height

  20. 20

    UITableView with 3 custom views and dynamic height

  21. 21

    How to resize the UITableView row height in Objective C

  22. 22

    How to set height constraint of UITableView according to dynamic height cells?

  23. 23

    Set height of UITableView which contain dynamic Cell Height

  24. 24

    UITableView: automatically set height for the row and fix it with max height constant

  25. 25

    Dynamic UITableView cell height with AutoLayout with Dynamic Type Labels

  26. 26

    UIStackView not updating after updating height of subview (UITableView with no scroll) while inside a ScrollView

  27. 27

    Make multiple links in a row the same dynamic height

  28. 28

    uicollectionview's dynamic height as per row values

  29. 29

    UITableViewCell dynamic height breaks after insert row

HotTag

Archive