如何让UITableview重新加载到页面顶部?

问题描述 投票:29回答:12

当我从下面调用以下内容时,当我重新加载表数据时,我试图让UITableview转到页面顶部

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

// A bunch of code …

[TableView reloadData];
}

同样,我还希望能够在重新加载表数据时转到特定的部分。

我尝试放置以下内容,这似乎只适用于重新加载之前和之后的行,但没有任何反应:

[TableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop  animated:YES];
iphone cocoa-touch tableview
12个回答
64
投票

这是你可以做到的另一种方式:

Objective-C的

[tableView setContentOffset:CGPointZero animated:YES];

斯威夫特3

tableView.setContentOffset(.zero, animated: true)

可能是最简单,最直接的方式。


1
投票

对于仍在寻找解决方案的人,您可以使用UITableView的以下扩展名。

包括第一部分是否有行的支票。直到带有行的部分出现然后滚动到那个部分。

extension UITableView {

    func scrollToFirst() {

        self.reloadData() // if you don't want to reload data, remove this one.
        for i in 0..<self.numberOfSections {

            if self.numberOfRows(inSection: i) != 0 {

                self.scrollToRow(at: IndexPath(row: 0, section: i), at: .top, animated: true) 
                break 
            }
        }
    }
}

希望对你有所帮助。


0
投票

如果在重新加载之前滚动并且行数减少,则可能会出现一些奇怪的动画行为。要确保重新加载后滚动,请使用如下方法:

- (void)reloadTableViewAndScrollToTop:(BOOL)scrollToTop {
    [self.tableView reloadData];
    if (scrollToTop) {
        [self.tableView setContentOffset:CGPointZero animated:YES];
    }
}

0
投票

在考虑了上面讨论的选项后,我的解决方案版本如下。它适用于iOS 11和12,适用于UICollectionView和UITableView。

UICollectionView:

DispatchQueue.main.async { [weak self] in
    guard self?.<your model object>.first != nil else { return }

    self?.collectionView.scrollToItem(at: IndexPath(row: 0, section: 0),
                               at: .top,
                                     animated: false)
}

UITableView的:

DispatchQueue.main.async { [weak self] in
    guard self?.<your model object>.first != nil else { return }

    self?.collectionView.scrollToRow(at: IndexPath(row: 0, section: 0),
                               at: .top,
                                     animated: false)
}

29
投票

在阅读了这里和其他地方的所有答案后,我终于找到了一个可靠的解决方案,并且在加载数据后没有显示滚动。我的答案基于这个post和我的观察,如果你使用内容插入,你需要一个负偏移:

func reloadAndScrollToTop() {
    tableView.reloadData()
    tableView.layoutIfNeeded()
    tableView.contentOffset = CGPoint(x: 0, y: -tableView.contentInset.top)
}

18
投票

要滚动到特定部分,您需要指定它的索引路径:

NSIndexPath *topPath = [NSIndexPath indexPathForRow:0 inSection:0];
[TableView scrollToRowAtIndexPath:topPath
                 atScrollPosition:UITableViewScrollPositionTop
                         animated:YES];

如果您不确定tableView中的行数。使用以下内容:

NSIndexPath *topPath = [NSIndexPath indexPathForRow:NSNotFound inSection:0];
[TableView scrollToRowAtIndexPath:topPath
                 atScrollPosition:UITableViewScrollPositionTop
                         animated:YES];

18
投票

这对我有用。

tableView.scrollToRow(at: IndexPath.init(row: 0, section: 0), at: .top, animated: true)

10
投票

没有动画

我在iOS11上,使用带有粘性标题的普通tableview样式,并且在某种程度上我只有这样才能正常工作才能在没有任何奇怪的闪烁/动画行为的重新加载后将tableview真正放在顶部才能按此顺序使用这些方法其中所有这些都是必要的:

[self.tableView setContentOffset:CGPointZero animated:NO];
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:CGPointZero animated:NO];

我很认真,所有这些都是必要的,尽管看起来第一行根本不相关。哦是的,也很重要,不要用这个:

self.tableView.contentOffset = CGPointZero;

您会认为它与“setContentOffset animated:FALSE”相同,但显然它不是! Apple对此方法的处理方式不同,在我的情况下,只有在使用带动画的完整方法时才有效:FALSE。

动画

我也想用一个很好的滚动动画来尝试这个。内容偏移方法似乎仍然会导致一些奇怪的动画行为。在一些试验和错误之后,我得到这个有一个很好的动画的唯一方法是这些方法按照这个确切的顺序:

[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:TRUE];

警告,确保在运行最后一行代码之前至少有一行以避免崩溃:)

我希望有一天能帮助别人!


4
投票

UITableView是UIScrollView的子类,因此您还可以使用:

[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

1
投票

在swift 3.1中

DispatchQueue.main.async(execute: {

        self.TableView.reloadData()
        self.TableView.contentOffset = .zero

    })

1
投票

您必须使用以下代码行在表视图的第一行滚动UITableView:

self.yourTableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)

1
投票

由于解释不完整,我对这个问题的一些答案感到有些困惑。根据我的收集,有两条路线可以完成OP的要求,它们如下:

1)如果动画不是必需的,我建议在使用其中一种偏移方法加载数据之前重置滚动位置。你应该在reloadData之前运行offset的原因是reloadData是异步运行的。如果在重新加载后运行偏移量,则滚动位置可能会从顶部向下几行。

tableView.setContentOffset(.zero, animated: false)
tableView.reloadData()

2)如果需要动画,请在使用scrollToRow运行reloadData后将滚动条定位到顶行。 scrollToRow在这里工作的原因是它将你定位在表的顶部,相对于偏移方法,它使你相对于已经加载的数据。

tableView.reloadData()
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
© www.soinside.com 2019 - 2024. All rights reserved.