在保持滚动位置的同时动画化所有 UITableViewCells 的高度变化

Posted

技术标签:

【中文标题】在保持滚动位置的同时动画化所有 UITableViewCells 的高度变化【英文标题】:Animate height change of all UITableViewCells while maintaining scroll position 【发布时间】:2013-08-22 00:59:44 【问题描述】:

我希望能够扩展/收缩 UITableView 中的所有单元格,同时保持当前位置并使更改为高度更改设置动画。本质上,它应该看起来像当前视图中的单元格正在扩展/收缩,并且滚动位置保持不变。

我可以通过具有不同高度的 2 个状态并调用来扩展/联系单元格

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

我已经尝试通过以下方式保持相同的位置(不是 100% 这个计算是正确的):

        //calculate the new position it should scroll to based on new cell height
        CGFloat posFromTop = self.tableView.contentOffset.y;
        CGFloat newDistance = 0;

            if(expandedState)
            
                CGFloat cellsFromTop = posFromTop / kExpandedCellHeight;
                newDistance = cellsFromTop * kCollapsedCellHeight;
            
            else
            
                CGFloat cellsFromTop = posFromTop / kMGLCollapsedCellHeight;
                newDistance = cellsFromTop * kMGLExpandedCellHeight;
            
        

//reload section
        [self.tableView setContentOffset:CGPointMake(0, newDistance) animated:YES];
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

虽然这似乎是一种工作,但它并没有在动画时保持位置,它会闪烁白色,因此它是不稳定的,并且看起来 tableView 在重新加载期间不会保持静止。

任何人都有一种方法可以在保持相同位置的同时平滑地设置所有单元格的高度?

【问题讨论】:

你找到解决办法了吗? 【参考方案1】:

尝试替换

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation: UITableViewRowAnimationAutomatic];

[self.tableView beginUpdates];
[self.tableView endUpdates];

后者将获取当前单元格并更新它们的大小。使用自动动画重新加载部分很可能使用淡入淡出动画,该动画会在新高度生成新单元格并在现有单元格和新单元格之间淡入淡出,这可能不是您想要的。

【讨论】:

开始/结束更新似乎有助于过渡,但仍然不是很顺利,因为仍然存在将表格保持在同一位置的问题。 尝试在表格视图更新后调用setContentOffset:。问题可能是在您设置内容偏移量后表格正在更新其内容大小,因此它实际上并没有正确地保持在原位。【参考方案2】:

您可能会发现执行第一个折叠动画需要多少时间,假设它恰好需要 1 秒。那我想你可以这样说:

[UIView animateWithDuration:1.0 animations:^
    [self.tableView setContentOffset:CGPointMake(0, newDistance) animated:NO];
]; 

这将在 1 秒内执行动画,其中您的 tableView 从当前 contentOffset 开始,并以您想要的 contentOffset 结束。我从来没有使用过UITableViewRowAnimationAutomatic,或者tableView的动画,但也许你也可以尝试一些其他的值。

实际上,如果您明白我的意思,您也许可以将这两个动作放入同一个动画中。这也可以让你控制一切的持续时间。我不知道这是否可行,我现在无法测试它,但看起来像这样:

[UIView animateWithDuration:1.0 animations:^
    [self.tableView setContentOffset:CGPointMake(0, newDistance) animated:NO];
    [self.tableView setRowHeight:newHeight];
]; 

我怀疑这种特定的方法是否真的存在,但我相信你明白我在说什么,如果有类似的东西,你会找到它。甚至可能在您的原始调用中使用 nil 作为动画参数。

(还有一些叫做 beginUpdatesendUpdates 的东西,如果这不起作用,你可以看看,但我不确定是否可以改变高度)

【讨论】:

我尝试对 UIView 进行动画处理,但并没有退出同时转换高度的工作。不过这是个好主意。 @user1218464 您是否尝试过第二个想法,即在同一动画序列中为滚动和高度设置动画?不仅仅是身高? 表格没有'setRowHeight'或类似的东西。因此,您必须开始更新/结束更新或重新加载表格/部分才能调整高度。所以不可能(看起来)把它放在动画里。 @user1218464 developer.apple.com/library/ios/documentation/uikit/reference/… 您可能必须找到绕过heightForRowAtIndexPath 的方法才能使其工作.. 就像拥有一个布尔值bool rowsAreExpanded,并检查heightForRow.. 内部是否为真.

以上是关于在保持滚动位置的同时动画化所有 UITableViewCells 的高度变化的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中保持滚动视图偏移的同时添加列表视图项

如何应用滚动平均函数,同时及时保持所有具有重复索引的观测值

UITableView 不会滚动到某个位置

iOS 10 Safari:防止在固定覆盖层后面滚动并保持滚动位置

为 UITableview 的高度设置动画时,滚动手势识别器保持相同大小

JQuery 动画运行不流畅,滚动条闪烁很多,DIV 动画化