Сохранение позиции прокрутки после перезагрузки в tableView
У меня есть TableView. Когда пользователь нажимает на одну из записей, я проверяю ее свойства и, основываясь на этом, я фильтрую результаты и показываю только похожие результаты - поэтому мне нужно обновить tableView.
Проблема в том, что пользователь может прокручивать вверх / вниз табличное представление. Мне нужно прокрутить tableView, чтобы ячейка была точно такой же UITableViewScrollPosition
как перед обновлением.
Очевидно, я сохраняю последний нажатый элемент
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
_lastSelectedItem = [self itemForIndexPath:indexPath];
}
Затем после перезагрузки tableView:
NSIndexPath *indexPath = [self indexPathForItem:_lastSelectedItem];
if (_tableView.numberOfSections > indexPath.section && [_tableView numberOfRowsInSection:indexPath.section] > indexPath.row) {
[_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
_lastSelectedItem = nil;
}
Было бы хорошо, но... пользователь не мог закончить на UITableViewScrollPositionMiddle
, Он мог закончить прокрутку на UITableViewScrollPositionTop
или же UITableViewScrollPositionBottom
или даже где-то между.
-- редактировать --
Вычисление с помощью смещения также проблематично, так как смещение - это разница между началом просмотра и положением прокрутки верхней таблицы... хотя меня это значение не интересует:/.
1 ответ
Поскольку моя структура была довольно сложной, я закончил, чтобы сделать это таким образом (например, расширяемые секции и т. Д.). Пожалуйста, не забывайте, что я экономлю _lastSelectedItem
, который является моим объектом в источнике данных, так как indexPath изменится после обновления.
- (void)refresh {
[self saveLastScrollPosition];
[self reloadData]; // inside we reload data + reload tableView
[self scrollToLastScrollPosition];
}
- (NSInteger)heightToMinYOfCellAtIndexPath:(NSIndexPath *)indexPath {
NSInteger sections = indexPath.section;
NSInteger totalRows = 0;
for (NSInteger section = 0; section < indexPath.section; section++) {
totalRows += [self.tableView numberOfRowsInSection:section];
}
totalRows += indexPath.row;
return ((sections + 1) * kHeaderHeight + totalRows * kRowHeight);
}
- (void)saveLastScrollPosition {
if (_lastSelectedItem) { // make sure we have that item selected
NSIndexPath *indexPath = [self itemForItem:_lastSelectedItem];
NSInteger aboveItemHeight = [self heightToMinYOfCellAtIndexPath:indexPath];
CGFloat contentOffsetY = self.tableView.contentOffset.y;
_previousOffset = aboveItemHeight - contentOffsetY;
}
}
- (void)scrollToLastScrollPostion {
if (_lastSelectedItem) { // make sure we have that item selected
NSIndexPath *indexPath = [self itemForItem:_lastSelectedItem];
if (self.tableView.numberOfSections > indexPath.section && [self.tableView numberOfRowsInSection:indexPath.section] > indexPath.row) { // make sure the indexPath still exist after reload
NSInteger aboveItemHeight = [self heightToMinYOfCellAtIndexPath:indexPath]; // height of items above selected index
CGPoint offset = CGPointMake(0.f, aboveItemHeight - _previousOffset);
// in case index should be higher: eg earlier item was at index (4,8) now is at (0,0)
if (offset.y < 0) {
offset.y = 0;
}
[self.tableView setContentOffset:offset animated:NO]; // just jump, user shouldn't see this
_previousOffset = 0; // forget the calculated values
_lastSelectedItem = nil;
}
}
}