如何使用自动布局animationUITableViewCell高度?

有关堆栈溢出关于UITableViewCell高度animation很多类似的问题,但没有什么适用于新的iOS8自动布局驱动的表视图。 我的问题:

定制单元格:

 @property (weak, nonatomic) IBOutlet iCarousel *carouselView; @property (weak, nonatomic) IBOutlet UIPageControl *pageControl; @property (weak, nonatomic) IBOutlet UIButton *seeAllButton; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *carouselHeightConstraint; 

注意carouselHeightConstraint 。 这是内容视图的子视图(唯一的子视图)的高度限制。

例如,高度设置为230.0f 。 在第一次加载它看起来像: 在这里输入图像说明

然后,在查看所有操作我想展开单元格,我的代码:

 - (IBAction)seeAllButtonAction:(id)sender { BOOL vertical = !self.carouselCell.carouselView.vertical; self.carouselCell.carouselView.type = vertical ? iCarouselTypeCylinder : iCarouselTypeLinear; self.carouselCell.carouselView.vertical = vertical; [UIView transitionWithView:self.carouselCell.carouselView duration:0.2 options:0 animations:^{ self.carouselCell.carouselHeightConstraint.constant = vertical ? CGRectGetHeight(self.tableView.frame) : 230; [self.carouselCell setNeedsUpdateConstraints]; [self.carouselCell updateConstraintsIfNeeded]; [self.tableView beginUpdates]; [self.tableView endUpdates]; completion:^(BOOL finished) { }]; } 

正如你所看到的,我尝试使用这个古老的解决scheme:
你可以在UITableViewCell上select一个高度变化的animation吗?

结果是:

在这里输入图像说明

我的细胞缩小44.0f高度。

题:

为什么会发生? 我希望看到我的单元格顺利扩展自动layot的魔力。

注意:
我不想用-tableView:heightForRowAtIndexPath: 这是自动布局时代,对吧?

以下为我工作:

制备:

  1. viewDidLoad告诉表视图使用自定义单元格:

     tableView.rowHeight = UITableViewAutomaticDimension; tableView.estimatedRowHeight = 44; // Some average height of your cells 
  2. 像平常一样添加约束,但将它们添加到单元格的contentView

animation高度变化:

假设你改变一个约束的constant

 myConstraint.constant = newValue; 

…或者你添加/删除约束。

要使此更改生效,请按以下步骤操作:

  1. 告诉contentView来改变animation:

     [UIView animateWithDuration: 0.3 animations: ^{ [cell.contentView layoutIfNeeded] }]; // Or self.contentView if you're doing this from your own cell subclass 
  2. 然后通过animation告诉桌面视图对高度变化做出反应

     [tableView beginUpdates]; [tableView endUpdates]; 

第一步的持续时间为0.3,看起来是UITableView在调用begin / endUpdates时用于animation的持续时间。

奖金 – 更改高度,无需animation,无需重新加载整个表格:

如果你想做同样的事情,但没有animation,那么做这个,而不是:

 [cell.contentView layoutIfNeeded]; [UIView setAnimationsEnabled: FALSE]; [tableView beginUpdates]; [tableView endUpdates]; [UIView setAnimationsEnabled: TRUE]; 

概要:

 // Height changing code here: // ... if (animate) { [UIView animateWithDuration: 0.3 animations: ^{ [cell.contentView layoutIfNeeded]; }]; [tableView beginUpdates]; [tableView endUpdates]; } else { [cell.contentView layoutIfNeeded]; [UIView setAnimationsEnabled: FALSE]; [tableView beginUpdates]; [tableView endUpdates]; [UIView setAnimationsEnabled: TRUE]; } 

你可以查看我的实现,当用户在这里select时展开的单元格(纯Swift和纯自动布局 – 真正的未来之路)。

我想补充几点Alex的答案。

如果您在cellForRowAtIndexPath或willDisplayCell中调用beginUpdates和endUpdates,您的应用程序将崩溃。 在animation增加单元格之后,您可能希望在滚动到tableView后保持不变。 您可能还希望其余的单元格保持其高度相同。 但请记住,细胞是可重复使用的,所以你可能最终与其他细胞增加高度。

因此,您将不得不在cellForRowAtIndexPath中设置约束条件,具体取决于它所表示的项目。 但是如果以后再调用layoutIfNeeded,它将会显示一个警告和你的约束。 我的信念是,它试图在计算新的高度之前生成单元布局。

 public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { ... myConstraint.constant = itemForCell.value == "x" ? 50 : 20 // stop right here cell.layoutIfNeeded() <- don't do this or some of your constraints will break beginUpdates() <-- if you do this your app will crash endUpdates() <-- same here