gpt4 book ai didi

ios - 为什么我的 UITableView 在插入或删除行时出现 "jump"?

转载 作者:IT王子 更新时间:2023-10-29 08:05:06 26 4
gpt4 key购买 nike

(很高兴接受 Swift 或 Objective-C 的答案)

我的 TableView 有几个部分,按下按钮时,我想在部分 0 的末尾插入一行。再次按下按钮,我想删除同一行。我几乎可以工作的代码如下所示:

// model is an array of mutable arrays, one for each section

- (void)pressedAddRemove:(id)sender {
self.adding = !self.adding; // this is a BOOL property
self.navigationItem.rightBarButtonItem.title = (self.adding)? @"Remove" : @"Add";

// if adding, add an object to the end of section 0
// tell the table view to insert at that index path

[self.tableView beginUpdates];
NSMutableArray *sectionArray = self.model[0];
if (self.adding) {
NSIndexPath *insertionPath = [NSIndexPath indexPathForRow:sectionArray.count inSection:0];
[sectionArray addObject:@{}];
[self.tableView insertRowsAtIndexPaths:@[insertionPath] withRowAnimation:UITableViewRowAnimationAutomatic];

// if removing, remove the object from the end of section 0
// tell the table view to remove at that index path

} else {
NSIndexPath *removalPath = [NSIndexPath indexPathForRow:sectionArray.count-1 inSection:0];
[sectionArray removeObject:[sectionArray lastObject]];
[self.tableView deleteRowsAtIndexPaths:@[removalPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[self.tableView endUpdates];
}

这有时会正常运行,但有时不会正常运行,具体取决于滚动 TableView 的位置:

  • 第 0 节在最上面,contentOffset.y == 0:效果很好,插入了行,第 0 节下面的内容向下动画
  • 第 0 节不可见,因为表格滚动经过它:效果很好,新行下方的可见内容向下动画,就好像在其上方插入了一行。
  • 但是:如果表格 View 滚动了一点,那么第 0 部分的那部分是可见的:它会出错。在一个框架中,表格 View 中的所有内容都跳起来(内容偏移量增加)然后,通过动画,插入新行并且表格 View 内容向下滚动(内容偏移量减少)。一切都在它应该在的地方结束,但是这个过程看起来非常糟糕,因为在开始时有单帧“跳跃”。

我可以通过“Debug->Toggle Slow Animations”在模拟器的慢动作中看到这种情况。同样的问题反过来出现在删除上。

我发现偏移量跳跃的大小与表格滚动到第 0 节的距离有关:偏移量很小时跳跃很小。随着滚动接近第 0 部分总高度的一半,跳跃变得更大(问题在这里最糟糕,跳跃 == 部分高度的一半)。进一步滚动,跳跃变小。当表格滚动到只有一小部分部分 0 仍然可见时,跳跃很小。

你能帮我理解这是为什么以及如何解决吗?

最佳答案

在 iOS 11 上,UITableView 默认使用估计的行高。

在插入/重新加载或删除行时会导致不可预知的行为,因为 UITableView 大多数时候的内容大小不正确:

为了避免过多的布局计算,tableView 只在每次调用 cellForRow 时询问 heightForRow 并记住它(在正常模式下,tableView 询问 heightForRow 用于 tableView 的所有索引路径)。其余单元格的高度等于 estimatedRowHeight 值,直到它们相应的 cellForRow 被调用。

// estimatedRowHeight mode
contentSize.height = numberOfRowsNotYetOnScreen * estimatedRowHeight + numberOfRowsDisplayedAtLeastOnce * heightOfRow

// normal mode
contentSize.height = heightOfRow * numberOfCells

我想 UIKit 很难正确地为变化设置动画是因为这个技巧。

一种解决方案是通过将 estimatedRowHeight 设置为 0 并为每个单元格实现 heightForRow 来禁用 estimatedRowHeight 模式。

当然,如果您的单元格具有动态高度(大部分时间进行繁重的布局计算,因此您有充分的理由使用 estimatedRowHeight),您必须找到一种方法来重现 estimatedRowHeight 优化而不影响 tableView 的 contentSize。看看AsyncDisplayKitUITableView-FDTemplateLayoutCell .

另一种解决方案是尝试找到适合的estimatedRowHeight。从 iOS 10 开始,您还可以尝试使用 UITableView.automaticDimension。 UIKit 会为你找到一个值:

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension

在 iOS 11 上,它已经是默认值。

关于ios - 为什么我的 UITableView 在插入或删除行时出现 "jump"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48154984/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com