我有一个自定义UIView用作UITableView的节头.我希望能够通过更改标题视图的高度来扩展和折叠标题视图,并为此更改设置动画.
标题视图包含两个使用约束布局的标签.折叠视图时,放置在底部的标签的高度约束将设置为0.
当我按下折叠/展开按钮时,我更改了一个由tableView返回的headerHeight变量:heightForHeaderInSection:.在这里,我还更改了高度约束的值.我在tableView.beginUpdates()和tableView.endUpdates()中都做了,但标题视图不会动画.在我开始滚动表格视图之前,它甚至不会使用新的高度.或者我使用tableView.reloadSections(NSIndexSet(index:0),withRowAnimation:.Automatic),它会对标题视图的高度进行动画处理,但会弄乱其中的子视图(顶部标签会在整个标题视图中垂直拉伸,即使它有一个固定的高度).
有没有人有一个解决方案,使用约束正确地动画标题视图高度和它的子视图?
下面是HeaderView的代码:
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]|",views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[titleLabel]-(>=0)-|",views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(>=0)-[subtitleLabel]|",views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[expandButton]-(>=0)-|",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,constant: 20) subtitleLabel.addConstraint(subtitleLabelHeightConstraint) } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
和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 } }
我还在https://github.com/lammertw/DynamicSectionHeader用代码创建了一个项目.
解决方法
尝试替换这个:
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) }
这样:
func toggleExpansion() { if headerHeight == 60 { headerHeight = 40 headerView.subtitleLabelHeightConstraint.constant = 0 } else { headerHeight = 60 headerView.subtitleLabelHeightConstraint.constant = 20 } tableView.beginUpdates() tableView.endUpdates() // Alternatively use tableView.reloadSections instead of begin and end updates: // tableView.reloadSections(NSIndexSet(index: 0),withRowAnimation: .Automatic) }