Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maintain offset when reloadRowsAtIndexPaths

I'm trying to reload a single tableViewCell but it scrolls to the top every time I do it... I'm not adding nor deleting cells, I just want to change the color of the selected cells.

This is what I do in the 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];
}

And this is what I do in the 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];

But it just jumps, any suggestion?

P.S I followed this thread but it didn't solved my question Calling reloadRowsAtIndexPaths removes tableView contentOffset

like image 990
mtet88 Avatar asked Nov 24 '14 10:11

mtet88


1 Answers

Because for some mysterious reason the table view determines the new offset after reloading some cells using the estimated row height you want to make sure the tableView:estimatedHeightForRowAtIndexPath returns correct data for cells that have already been rendered. To accomplish this you can cache the seen row heights in a dictionary, then use this correct data (or your estimate for not already loaded cells.)

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
}

(HUGE thanks to eyuelt for the insight that estimated row height is used to determine the new offset.)

like image 173
Daniel Schlaug Avatar answered Sep 24 '22 17:09

Daniel Schlaug