自定义 UITableViewCell 高度会产生不正确的动画

Posted

技术标签:

【中文标题】自定义 UITableViewCell 高度会产生不正确的动画【英文标题】:Custom UITableViewCell height yields improper animation 【发布时间】:2013-09-04 13:35:46 【问题描述】:

我目前正在使用一个 uitableview,它主要包含 44pts 的标准尺寸单元格。但是,有一对更大,大约 160pts。

在本例中,有 2 行高度为 44pts,较大的 160pts 行插入下方,位于该部分的索引 2 处。

移除调用:

- (void)removeRowInSection:(TableViewSection *)section atIndex:(NSUInteger)index 
    NSUInteger sectionIndex = [self.sections indexOfObject:section];

    NSIndexPath *removalPath = [NSIndexPath indexPathForRow:index inSection:sectionIndex];

    [self.tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:@[removalPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView endUpdates];

代表电话:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    TableViewSection *section = [self sectionAtIndex:indexPath.section];

    return [section heightForRowAtIndex:indexPath.row];

部分调用:

- (NSInteger)heightForRowAtIndex:(NSInteger)index 
    StandardCell *cell = (StandardCell *)[self.list objectAtIndex:index];

    return cell.height;

手机通话:

- (CGFloat)height 
    return 160;

让我感到困惑的是,当我从表格中删除较大的行时,它们开始动画,移动到上面一行的下方。但是当它们到达某个点时,大约动画的 1/4 处,它们会消失而不是完成动画。

似乎表格以它只有 44 点的概念为行设置动画,然后一旦达到 44 点位于上方行下方的点,它就会从表格中删除。我忽略了哪些细节可以为表格提供正确的概念以自动为行删除设置动画?

感谢您的帮助。

更新: 我尝试注释掉上面的高度函数(它覆盖了返回 44 的默认值)。这会产生没有跳过的正确动画。 FWIW

【问题讨论】:

我无法重现这一点。您能否分享更多详细信息,例如 a) 更多视图控制器代码,b) 存在哪些索引路径以及它们的高度,c) 您使用哪个动画选项针对哪些索引路径进行了哪些批量更新? 感谢您的帮助。我添加了唯一正在执行的其他代码,即删除调用。它似乎适用于任何其他行。 我看不出你的代码有什么问题。如果有帮助,这里是my sample project 的链接。动画对我来说看起来很流畅。但是,如果要删除的单元格下方没有足够的行,它可能会在动画期间显示在底部。淡入淡出的动画风格看起来更好 IMO。 好的,现在我根据您的更新信息复制了它。 a)被删除的单元格是最后一个单元格和 b)您正在使用顶部或底部动画类型的关键。我认为最简单的解决方案是使用淡入淡出动画类型。 有什么办法可以避免使用淡入淡出动画类型?在某些情况下,最后两行(44pt 和 160pt)会一起被删除,这意味着一个会褪色,一个会向上滑动。而且我宁愿不要让它们都褪色。 【参考方案1】:

解决此问题的一种方法是在删除之前将行高设置为 44:

//mark index paths being deleted and trigger `contentSize` update
self.indexPathsBeingDeleted = [NSMutableArray arrayWithArray:@[indexPath]];
[tableView beginUpdates];
[tableView endUpdates];

//delete row
[self.tableView deleteRowsAtIndexPaths:@[removalPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];

然后在你的heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    if ([self.indexPathsBeingDeleted containsObject:indexPath]) 
        //return normal height if cell is being deleted
        [self.indexPathsBeingDeleted removeObject:indexPath];
        return 44;
    
    if (<test for tall row>) 
        return 160;
    
    return 44;

有一些簿记正在进行以跟踪被删除的索引路径。可能有更清洁的方法可以做到这一点。这只是想到的第一件事。这是working sample project。

【讨论】:

感谢您的想法。虽然,我不太喜欢变通办法,但我会看看这对我有用。不过肯定有其他技巧,因为我已经看到 ios7 提醒应用程序使用单元内日期选择器做同样的事情......也许下周 api 会改变。 我猜日期选择器是一个扩展单元格,而不是两个单独的单元格。日期单元格的隐藏和显示对我来说就像一个淡入淡出的动画。我的测试项目在 [redacted] 中的表现也好不到哪里去。 我想出了一个非常简单的方法来实现您在我的项目中将行高更改为 0 的想法。基本上我只是在表格中一直有高行,除非我需要显示它,而不是插入它,我适当地更改高度并更新表格。像魅力一样工作,看起来很棒!再次感谢!

以上是关于自定义 UITableViewCell 高度会产生不正确的动画的主要内容,如果未能解决你的问题,请参考以下文章

根据视图更改自定义 UITableViewCell 高度

自定义 UITableViewCell 的动态高度问题

自定义 UITableViewCell 和调整单元格高度

关于单元重用的自定义 UITableViewCell 约束问题

iOS8中自定义UITableViewCell动态高度的内容有不同的宽度

改变 UITableViewCell 高度的自定义动画