reloadRowsAtIndexPaths 时保持偏移

Posted

技术标签:

【中文标题】reloadRowsAtIndexPaths 时保持偏移【英文标题】:Maintain offset when reloadRowsAtIndexPaths 【发布时间】:2015-01-22 01:12:12 【问题描述】:

我正在尝试重新加载单个 tableViewCell,但每次执行此操作时它都会滚动到顶部...我没有添加或删除单元格,我只是想更改所选单元格的颜色。

这就是我在 cellForRowAtIndexPath 中所做的:

SMPChoiceViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ChoiceCell" forIndexPath:indexPath];
SMPChoice *choice = self.choices[indexPath.row - 1];
cell.choiceTextLabel.text = choice.text;

if ([self.selectedChoices indexOfObject:choice] != NSNotFound) 
  cell.choiceTextLabel.textColor = [UIColor purpleColor];
 else 
  cell.choiceTextLabel.textColor = [UIColor blackColor];

这就是我在 didSelectRowAtIndexPath 中所做的

if ([self.selectedChoices indexOfObject:choice] != NSNotFound) 
  [self.selectedChoices removeObject:choice];
 else 
  [self.selectedChoices addObject:choice];


CGPoint offSet = [tableView contentOffset];

[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView setContentOffset:offSet animated:NO];

但它只是跳跃,有什么建议吗?

附言 我关注了这个帖子,但它没有解决我的问题Calling reloadRowsAtIndexPaths removes tableView contentOffset

【问题讨论】:

尝试 UITableViewRowAnimationNone 并删除 [tableView setContentOffset:offSet animated:NO]; 嗨 Sathya... 它仍然滚动到顶部,现在它没有那么好的褪色效果嘿嘿嘿:'( 【参考方案1】:

OBJ-C版大牛的回答:

//rowHeightForIndexPath is an NSMutableDictionary
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
    [self.rowHeightForIndexPath setObject:@(cell.frame.size.height) forKey:indexPath];


- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath 
    NSNumber *cachedHeight = [self.rowHeightForIndexPath objectForKey:indexPath];

    return cachedHeight ? cachedHeight.floatValue : UITableViewAutomaticDimension;

【讨论】:

【参考方案2】:

由于某种神秘的原因,表格视图会在使用估计的行高重新加载某些单元格后确定新的偏移量,您希望确保 tableView:estimatedHeightForRowAtIndexPath 为已渲染的单元格返回正确的数据。为此,您可以将看到的行高缓存在字典中,然后使用此正确数据(或您对尚未加载的单元格的估计。)

fileprivate var heightForIndexPath = [NSIndexPath: CGFloat]()
fileprivate let averageRowHeight: CGFloat = 300 //your best estimate

//UITableViewDelegate

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) 
    heightForIndexPath[indexPath] = cell.frame.height


override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    return heightForIndexPath[indexPath] ?? averageRowHeight

(非常感谢 eyuelt 洞察到使用估计的行高来确定新的偏移量。)

【讨论】:

即使使用缓存的方法仍然有同样的问题。 这对我来说是一个快速简单的解决方案。任何高估或低估细胞高度的方法似乎都始终如一。当表重新加载新数据时,我还清除了缓存。【参考方案3】:

我知道这是一个老问题,但我遇到了同样的问题,在任何地方都找不到答案。

reloadRowsAtIndexPaths:withRowAnimation: 之后,tableView 使用tableView:estimatedHeightForRowAtIndexPath: 中给出的估计高度来确定其偏移量。因此,除非您返回的值是准确的,否则执行它将导致您的 tableView 的偏移量在重新加载后发生变化。我未实现tableView:estimatedHeightForRowAtIndexPath:,问题已解决。

【讨论】:

文档状态:“如果您没有估计,则返回 UITableViewAutomaticDimension”tableView:estimatedHeightForRowAtIndexPath:。您应该返回它而不是不实施它。取消实现该方法会导致我的单元格给出不准确的高度 @Gee.E UITableViewAutomaticDimension 是在 ios 8 中引入的。因此,如果您在 iOS 8 之前不需要支持任何东西,那么是的,您应该使用 UITableViewAutomaticDimension。我不确定为什么不实现该方法对您不起作用。 @Gee.E 即使返回 UITableViewAutomaticDimension 也只是一个小小的改进。 TableView 仍然会跳转到不同的位置。 是的,UITableViewAutomaticDimension 不是为我做的。 ...也没有实现该方法。

以上是关于reloadRowsAtIndexPaths 时保持偏移的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift 和 reloadRowsAtIndexPaths 编译错误

如何覆盖 reloadRowsAtIndexPath?

reloadRowsAtIndexPaths 崩溃;重新加载数据工作

解决使用DBeaver连接MySQL时保错-The server time zone value '?й???????' is unrecognized or represents m

解决使用DBeaver连接MySQL时保错-The server time zone value '?й???????' is unrecognized or represents m

reloadRowsAtIndexPaths 时保持偏移