reloadRowsAtIndexPaths时保持偏移量

时间:2014-11-24 10:42:02

标签: ios uitableview reload

我正在尝试重新加载一个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];

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

P.S 我遵循了这个帖子,但它没有解决我的问题Calling reloadRowsAtIndexPaths removes tableView contentOffset

3 个答案:

答案 0 :(得分:15)

由于某些神秘的原因,表视图在使用估计的行高重新加载某些单元格后确定新的偏移量,因此要确保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的洞察力,估计行高用于确定新的偏移量。)

答案 1 :(得分:10)

我知道这是一个老问题,但我有同样的问题,无法在任何地方找到答案。

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

答案 2 :(得分:0)

Daniel的答案的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;
}