3

我有一个tableView。当用户点击其中一个记录时,我检查它的属性,并基于此我筛选结果并显示相似的结果 - 所以我需要刷新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结束。他本来可以在UITableViewScrollPositionTopUITableViewScrollPositionBottom甚至之间的某个地方完成滚动。

- 编辑 -

通过偏移量计算也是有问题的,因为偏移的观点开始和顶级表滚动位置的区别。虽然我不关心这个值:/。

回答

0

由于我的结构相当复杂,我完成了这样做(例如可扩展部分等)。请注意,我正在保存_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; 
     } 
    } 
} 
+1

它可以通过一个'reloadDataAndScrollToLastPosition'公共方法放入UITableView类别中。 – ingaham 2015-01-07 16:54:34

+0

如果假设uitableview单元格高度动态,并且标题也是动态的,我们将使用多个自定义单元格,那么我们可以做些什么来解释它............. – 2015-10-25 13:30:40

+0

@JatiendarKumar解释取决于你是怎么做到的执行它。你可以看一下http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout,在页面中间你可以看到这样的方法'heightForBasicCellAtIndexPath:'并且把它当作你的例。 – Vive 2015-10-26 10:00:51