UITableView section header height change animation by constraint

I have a custom UIView that is used as the title of a UITableView section. I want to be able to expand and collapse the title view by changing its height and animating this change.

The header view contains two labels that it uses with restrictions. The height limit for the label below will be set to 0 when the view is minimized.

When I click the collapse / expand button, I change the headerHeight variable, which returns tableView:heightForHeaderInSection: Here I also change the value of the height limit. I do both in tableView.beginUpdates() and tableView.endUpdates() , but the title will not animate. He won't even use the new height until I start scrolling through the table view. As an alternative, I use tableView.reloadSections(NSIndexSet(index: 0), withRowAnimation: .Automatic) , which animates the height of the presentation of the header, but interferes with the subviews inside (the top label is stretched vertically throughout the view of the header, even if it has a fixed height) .

Does anyone have a solution that properly animates both the height of the presentation of the header and its subselects using constraints?

The following is the HeaderView code:

 class HeaderView: UIView { let titleLabel = UILabel() let subtitleLabel = UILabel() let expandButton = UIButton() var subtitleLabelHeightConstraint: NSLayoutConstraint! init() { super.init(frame: CGRectNull) titleLabel.setTranslatesAutoresizingMaskIntoConstraints(false) subtitleLabel.setTranslatesAutoresizingMaskIntoConstraints(false) expandButton.setTranslatesAutoresizingMaskIntoConstraints(false) expandButton.setTitle("Expand / Collapse", forState: .Normal) addSubview(titleLabel) addSubview(subtitleLabel) addSubview(expandButton) let views = ["titleLabel": titleLabel, "subtitleLabel": subtitleLabel, "expandButton": expandButton] addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[titleLabel]-[expandButton]|", options: nil, metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[subtitleLabel]|", options: nil, metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[titleLabel]-(>=0)-|", options: nil, metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(>=0)-[subtitleLabel]|", options: nil, metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[expandButton]-(>=0)-|", options: nil, metrics: nil, views: views)) titleLabel.addConstraint(NSLayoutConstraint(item: titleLabel, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 20)) subtitleLabelHeightConstraint = NSLayoutConstraint(item: subtitleLabel, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 20) subtitleLabel.addConstraint(subtitleLabelHeightConstraint) } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

And the code of the TableViewController :

 class TableViewController: UITableViewController { let headerView: HeaderView = { let view = HeaderView() view.titleLabel.text = "Title" view.subtitleLabel.text = "Subtitle" view.backgroundColor = UIColor.lightGrayColor() return view }() var headerHeight: CGFloat = 60 override func viewDidLoad() { super.viewDidLoad() headerView.expandButton.addTarget(self, action: "toggleExpansion", forControlEvents: .TouchUpInside) } func toggleExpansion() { tableView.beginUpdates() if headerHeight == 60 { headerHeight = 40 headerView.subtitleLabelHeightConstraint.constant = 0 } else { headerHeight = 60 headerView.subtitleLabelHeightConstraint.constant = 20 } tableView.endUpdates() // Alternatively use tableView.reloadSections instead of begin and end updates: // tableView.reloadSections(NSIndexSet(index: 0), withRowAnimation: .Automatic) } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 2 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell cell.textLabel?.text = "Cell" return cell } override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return headerHeight } override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return headerView } } 

I also created a https://github.com/lammertw/DynamicSectionHeader project with code.

+7
ios header uitableview
source share

No one has answered this question yet.

See related questions:

1473
Using auto layout in UITableView for dynamic layouts of cells and variable row heights
909
How to change restriction changes?
308
UITableView - change the color of the section title
61
How to detect a tableView cell affected or by clicking in quick
31
TableView header headers disappear swift
21
Expand and collapse table cells
0
after adding header cells are not displayed
0
Update or reload UITableView after completion of uninstall action in verbose view
0
Xib's custom UIView always has a height of 600 pt (UIView-Encapsulated-Layout-Height constraint)
0
The height of the UITableview automatically changes to full screen if the section title

All Articles