【问题标题】:Maintaining scroll position after reload in tableView在tableView中重新加载后保持滚动位置
【发布时间】:2014-11-18 14:47:38
【问题描述】:

我有一个 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 或什至介于两者之间完成滚动。

-- 编辑--

通过偏移量计算也是有问题的,因为偏移量是视图开始位置和顶部表格滚动位置之间的差异。而我对这个值不感兴趣:/。

【问题讨论】:

    标签: ios objective-c uitableview uiscrollview uiscrollviewdelegate


    【解决方案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;
            }
        }
    }
    

    【讨论】:

    • 它可以通过一个 'reloadDataAndScrollToLastPosition' 公共方法放入 UITableView 类别中。
    • 如果假设 uitableview 单元格高度是动态的,并且标题也是动态的,我们将使用多个自定义单元格,那么我们可以做什么,请解释一下......
    • @JatiendarKumar Explain 取决于你是如何实现它的。你可以看看raywenderlich.com/73602/…,在页面的中间你可以看到heightForBasicCellAtIndexPath:这样的方法,并以它为例。
    • 这是一个重复的帖子:stackoverflow.com/a/18844780/3705567 - 工作! (Y)
    猜你喜欢
    • 2012-10-16
    • 2015-02-20
    • 2017-02-23
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    相关资源
    最近更新 更多