关于UITableViewCell
高度动画的Stack Overflow上有很多类似的问题,但是对于新的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) {
}];
}
正如您所看到的,我尝试使用这个很好的旧解决方案:
Can you animate a height change on a UITableViewCell when selected?
结果:
我的单元格缩小到44.0f
高度。
为什么会这样?我希望看到我的细胞能够通过自动布局的魔力顺利扩展。
注意:
我不想使用-tableView:heightForRowAtIndexPath:
。它的自动布局时代,对吧?
答案 0 :(得分:43)
以下对我有用:
<强>制备强>
在viewDidLoad
上告诉表视图使用自调整单元格:
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 44; // Some average height of your cells
像往常一样添加约束,但将它们添加到单元格contentView
!
动画高度更改:
假设您更改了约束&#39; s constant
:
myConstraint.constant = newValue;
...或者您添加/删除约束。
要为此更改设置动画,请按以下步骤操作:
告诉contentView动画更改:
[UIView animateWithDuration: 0.3 animations: ^{ [cell.contentView layoutIfNeeded] }]; // Or self.contentView if you're doing this from your own cell subclass
然后告诉表视图使用动画
对高度变化作出反应[tableView beginUpdates];
[tableView endUpdates];
第一步的持续时间0.3似乎是UITableView在调用begin / endUpdates时用于动画的持续时间。
奖励 - 更改没有动画的高度,无需重新加载整个表格
如果你想做同样的事情,但没有动画,那就改为:
[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];
}
你可以查看我在用户选择它时扩展的单元格的实现here(纯粹的Swift&amp;纯自动布局 - 真正的未来之路)。
答案 1 :(得分:3)
我想在Alex的答案中加上几点。
如果在cellForRowAtIndexPath或willDisplayCell中调用beginUpdates和endUpdates,您的应用程序将崩溃。在为单元格增加动画后,您可能希望在滚动到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