iOS 8自行调整高度的单元格

我使用自定义的UITableViewCells创build了一个tableview

tableview.rowHeight = UITableViewAutomaticDimension;

用于testing一个创build的单个UIView并将其添加到cell.contentView具有以下约束。 (使用石工)

 - (void)updateConstraints { UIView *superview = self.contentView; if (!_didSetupConstraints) { [self.testView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview); make.height.equalTo(@10.0f); make.left.equalTo(superview); make.right.equalTo(superview); make.bottom.equalTo(superview); }]; _didSetupConstraints = YES; } [super updateConstraints]; } 

当我select一排我喜欢改变所选单元格的高度。 我是这样做的:

 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; [self.testView mas_updateConstraints:^(MASConstraintMaker *make) { if (selected) { make.height.equalTo(@100); } else { make.height.equalTo(@10); } }]; [UIView animateWithDuration:0.3f animations:^{ [super layoutIfNeeded]; }]; } 

这似乎工作,但Xcode投诉与以下错误:

Unable to simultaneously satisfy constraints.

然后问题是, contentView自己创build一个高度constaint(因为contentView.translatesAutoresizingMaskIntoConstraints = YES;默认情况下)。

因此,当updateConstraints第一次运行时,系统将在contentView上创build一个等于10.0f的高度约束

之后当setSelected...被调用时,我改变了我的testView的高度,使得testView.height (100.0f)和contentView.height (10.0f)之间发生冲突,并且由于testView被附加到contentView的底部(为了自我 – 大小的细胞工作)它给出了错误。

我试过设置contentView.translatesAutoresizingMaskIntoConstraints = NO; 但是看起来UITableViewCell无法真正为单元格找出合适的大小。 (有时太宽/太小)等

实施可以dynamic改变高度的自我调整细胞的正确方法是什么?

这里有两个问题:

1. AutoLayout消息: Unable to simultaneously satisfy constraints.

这是由于您更新自定义视图的height限制,但不更新contentViewheight限制。 因为您还将自定义视图的bottom约束设置为contentView bottom ,所以系统不能同时满足以下两个约束:自定义视图不能具有100的高度,并且同时连接到contentView的底部,而contentView仍然具有10的高度。

这个修复很容易。 您为contentView定义高度约束,并将其设置为您的自定义视图的高度:

 [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(self.testView); }]; 

这解决了这个问题。

2.更新单元格的高度

更新单元格高度并不是那么容易,因为单元格高度是由UITableViewController处理的,而不是单元格本身。 当然,你可以改变你的单元格的高度,但只要UITableViewController不给单元格足够的空间,就不会看到新的单元格高度。 你会看到你现在更高的单元将重叠下一个单元。

所以你需要一个方法来告诉UITableViewController它应该更新你的单元格的高度。 你可以通过调用reloadRowsAtIndexPaths:withRowAnimation: 这重新加载细胞,也很好地animation。 所以单元格不得不在UITableViewController上调用这个方法。 这里面临的挑战: UITableViewCell没有引用它的UITableViewController (它不应该)。

你可以做的是子类UITableViewCell并给它一个闭包属性,它可以在高度发生变化时执行:

 class DynamicHeightTableViewCell: UITableViewCell { var heightDidChange: (() -> Void)? ... 

现在,当你在你的UITableViewControllerDataSource出列一个单元格时,你设置了它的闭包:

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("DynamicHeightTableViewCell", forIndexPath: indexPath) if let customCell = cell as? DynamicHeightTableViewCell { customCell.heightDidChange = { [weak cell, weak tableView] in if let currentIndexPath = tableView?.indexPathForCell(cell!) { tableView?.reloadRowsAtIndexPaths([currentIndexPath], withRowAnimation: .Automatic) } } } return cell } 

然后,当单元格更改高度时,只需执行闭包,单元格就会重新加载:

 func theFunctionWhereTheHeightChanges() { // change the height heightDidChange?() }