UITableView-滚动到顶部


392

在表格视图中,我必须滚动到顶部。但是我不能保证第一个对象将是第0节,第0行。可能是我的表视图将从第5节开始。

所以当我打电话时我得到一个例外:

[mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

还有另一种滚动到表格视图顶部的方法吗?

Answers:


856

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

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

要么

[mainTableView setContentOffset:CGPointZero animated:YES];

在Swift中:

mainTableView.setContentOffset(CGPointZero, animated:true)

在Swift 3及更高版本中:

mainTableView.setContentOffset(.zero, animated: true)

9
我首先使用CGRectZero进行了尝试,它等效于CGRectMake(0,0,0,0)。这行不通,但是奇怪的是上面的行。我想它需要一个正的宽度和高度。谢谢。
凯勒

5
注意,如果要在scrollToRowAtIndexPath:中运行此动画,则将需要动画:否,以使表从正确的位置开始。希望能帮助到你!
Fattie 2014年

3
@ hasan83 CGRectMake(0,0,0,0)或CGRectZero不是可见的矩形。我还要说[mainTableView setContentOffset:CGPointZero动画:是];是更漂亮的表达。
catlan 2015年

8
有人注意到在iOS11中这一切都坏了,在某些情况下无法正确滚动吗?
彼得·拉皮苏

11
@PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true)似乎工作在iOS的11
乔丹小号

246

注意:此答案对iOS 11及更高版本无效。

我更喜欢

[mainTableView setContentOffset:CGPointZero animated:YES];

如果您在表格视图上有一个顶部插图,则必须减去它:

[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];

12
番茄,番茄。嗯...在书面上并没有很清楚地看到。
FreeAsInBeer '04年

14
这是当您具有表头或页脚视图并希望也将其包含时的最佳使用方法。
mafonya 2012年

6
这确实是一个清晰的代码,但是当您的顶部tableView的非零值时,它将不起作用contentInset。例如:tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);。如果是这种情况,请在您的代码中tableView滚动到(0.0f, 5.0f)
tolgamorf

25
解决我以前的评论的方法:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
tolgamorf

3
在iOS 11上,您应该考虑-scrollView.adjustedContentInset.top改用。
玛丽安·塞尔尼

79

可能的动作:

1个

func scrollToFirstRow() {
    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

2

func scrollToLastRow() {
    let indexPath = NSIndexPath(forRow: objects.count - 1, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}

3

func scrollToSelectedRow() {
    let selectedRows = self.tableView.indexPathsForSelectedRows
    if let selectedRow = selectedRows?[0] as? NSIndexPath {
        self.tableView.scrollToRowAtIndexPath(selectedRow, atScrollPosition: .Middle, animated: true)
    }
}

4

func scrollToHeader() {
    self.tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
}

5

func scrollToTop(){
    self.tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
}

禁用滚动到顶部:

func disableScrollsToTopPropertyOnAllSubviewsOf(view: UIView) {
    for subview in view.subviews {
        if let scrollView = subview as? UIScrollView {
            (scrollView as UIScrollView).scrollsToTop = false
        }
        self.disableScrollsToTopPropertyOnAllSubviewsOf(subview as UIView)
    }
}

根据要求修改并使用它。

斯威夫特4

  func scrollToFirstRow() {
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
  }

那就是完美的解决方案-scrollToFirstRow
Mehul

优秀的总结。如果拥有节标题,则必须使用option4 scrollToHeader。
文森特

有没有一种方法可以向上滚动到Tableview上方的搜索栏?
泰勒·鲁特

27

最好不要使用NSIndexPath(空表),也不要假设最高点是CGPointZero(内容插入),这就是我所使用的-

[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];

希望这可以帮助。


从iOS 11起不再有效
。– rmaddy

21

斯威夫特4

效果很好:

//self.tableView.reloadData() if you want to use this line remember to put it before 
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)

3
如果您的tableView中有tableHeaderView并且它是内联的(则与内容滚动)
不会-finneycanhelp

1
我既有一个普通的又有一个UITableViewStyleGrouped(标题随内容滚动),并且此代码有效。确保您在主线程中,并在视图出现(viewDidAppear)后启动此代码。如果仍然有问题,请尝试将代码放入其中:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
Alessandro Ornano,

1
谢谢。它会带您到第一个牢房。但是,它不显示表视图标题。
finneycanhelp

如果tableView由于某种原因为空(在0行的0部分中没有单元格),此操作将失败
Maxim Skryabin

17

我遇到了一个问题,要求在empty上尝试某些方法tableView。这是Swift 4的另一个处理空表视图的选项。

extension UITableView {
  func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
    return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
  }

  func scrollToTop(animated: Bool) {
    let indexPath = IndexPath(row: 0, section: 0)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
      self.scrollToRow(at: indexPath, at: .top, animated: animated)
    }
  }
}

用法:

// from yourViewController or yourTableViewController
tableView.scrollToTop(animated: true)//or false

这不考虑任何表头或节头。
rmaddy19年

16

请勿使用

 tableView.setContentOffset(.zero, animated: true)

有时可能会设置不正确的偏移量。例如,以我为例,该单元格实际上位于带有安全区域插图的视图上方。不好。

代替使用

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

1
完美的解决方案。
婴儿格鲁特

正是我想要的东西,谢谢。
西蒙

这些解决方案均无效。第一个在iOS 11或更高版本下不起作用。如果表视图具有表标题,或者第一部分具有节标题,则第二种方法不起作用,除非您确实确实希望第一行位于顶部并且不关心显示任何标题。
rmaddy19年

@rmaddy最好的解决方案是什么?
ScottyBlades

15

在iOS 11 adjustedContentInset上,无论呼叫状态栏是否可见,都可以在两种情况下正确滚动至顶部。

if (@available(iOS 11.0, *)) {
    [tableView setContentOffset:CGPointMake(0, -tableView.adjustedContentInset.top) animated:YES];
} else {
    [tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:YES];
}

迅速:

if #available(iOS 11.0, *) {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.adjustedContentInset.top), animated: true)
} else {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
}

12

对于具有的表contentInset,将内容偏移设置为CGPointZero无效。它将滚动到内容顶部,而不是滚动到桌面。

考虑内容插入会产生以下结果:

[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];

1
谢谢,我一直将其设置为CGPointZero,无法理解为什么会这样。
johnrechd

从iOS 11起不再有效
。– rmaddy

10

此代码让您将特定部分滚动到顶部

CGRect cellRect = [tableinstance rectForSection:section];
CGPoint origin = [tableinstacne convertPoint:cellRect.origin 
                                    fromView:<tableistance>];
[tableinstance setContentOffset:CGPointMake(0, origin.y)];

这是最简单的代码,它可以正常工作。我实际上放了CGPointMake(0.0f,0.0f)。干杯!
2014年

这段代码对于使该部分滚动到顶部非常有用
srinivas n


8

迅捷3

tableView.setContentOffset(CGPoint.zero, animated: true)

如果tableView.setContentOffset不工作。

采用:

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()

1
这对iOS 11或更高版本无效。
rmaddy19年

7

由于我tableView有各种各样的插图,所以这是唯一有效的方法:

迅捷3

if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 {
  tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}

迅捷2

if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
  tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}

这对我来说更有用
Tejzeratul

很好的答案,感谢您
Jeremy Bader

7

除了已经说过的内容之外,您还可以创建扩展名(Swift)或类别(目标C),以使其在将来变得更容易:

迅速:

extension UITableView {
    func scrollToTop(animated: Bool) {
        setContentOffset(CGPointZero, animated: animated)
    }
}

任何时候要将滚动给定的tableView滚动到顶部,都可以调用以下代码:

tableView.scrollToTop(animated: true)

2
从iOS 11起不再有效
。– rmaddy

6

我喜欢以下内容,因为它考虑了插图。如果没有插图,则它将滚动到顶部,因为插图将为0。

tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)

从iOS 11起不再有效
。– rmaddy

5

斯威夫特:

如果您没有tableView标头:

tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

如果是这样的话 :

tableView.setContentOffset(CGPointMake(0, -tableViewheader.frame.height   + UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

5

Swift 5,iOS 13

我知道这个问题已经有很多答案,但是根据我的经验,只有一种方法总是可行的:

tableView.scrollToRow(at: IndexPath(row: someArray.count - 1, section: 0), at: .bottom, animated: true)

如果您正在异步工作,使用键盘制作动画的表等,则其他答案通常会滚动到几乎最底部,而不是绝对底部。该方法每次都会使您到达表的绝对末尾。


您还需要检查是否有一个部分
Onur Tuna

4

这是我用来在iOS 11上正常工作的方法:

extension UIScrollView {
    func scrollToTop(animated: Bool) {
        var offset = contentOffset
        if #available(iOS 11, *) {
            offset.y = -adjustedContentInset.top
        } else {
            offset.y = -contentInset.top
        }
        setContentOffset(offset, animated: animated)
    }
}

4

在Swift 5中,非常感谢@Adrian的回答

extension UITableView{

    func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
        return indexPath.section < numberOfSections && indexPath.row < numberOfRows(inSection: indexPath.section)
    }

    func scrollToTop(_ animated: Bool = false) {
        let indexPath = IndexPath(row: 0, section: 0)
        if hasRowAtIndexPath(indexPath: indexPath) {
            scrollToRow(at: indexPath, at: .top, animated: animated)
        }
    }

}

用法:

tableView.scrollToTop()

2
1.这在Swift 4中也有效。2.如果有表头或节头,则此方法不起作用。
rmaddy19年

3

使用contentOffset不是正确的方法。这会更好,因为这是表格视图的自然方式

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

2
如果有表头或节头,则此方法将无效。
rmaddy19年

3

这是唯一对我有用的代码段

斯威夫特4:

    tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: true)

PS 70是标题和表格视图单元格的高度


这远不是滚动到顶部的正确方法。仅使用三行来设置内容偏移量是没有意义的。仅需要最后一行,但是硬编码特定偏移量不是正确的解决方案。
rmaddy19年

2
func scrollToTop() {
        NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
        [tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

在您希望UITableView滚动到顶部的任何地方调用此函数


2

Swift 4通过扩展,处理空表视图:

extension UITableView {
    func scrollToTop(animated: Bool) {
        self.setContentOffset(CGPoint.zero, animated: animated);
    }
}

从iOS 11开始无效
。– rmaddy

2

我使用tabBarController,并且在每个选项卡的tableview中都有一些部分,因此这对我来说是最佳解决方案。

extension UITableView {

    func scrollToTop(){

        for index in 0...numberOfSections - 1 {
            if numberOfSections > 0 && numberOfRows(inSection: index) > 0 {
                scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true)
                break
            }

            if index == numberOfSections - 1 {
                setContentOffset(.zero, animated: true)
                break
            }
        }

    }

}

1

我必须-1 *在状态栏和导航栏的总和上加上乘,因为它超出了屏幕的高度,

self.tableView.setContentOffset(CGPointMake(0 , -1 * 
  (self.navigationController!.navigationBar.height +  
  UIApplication.sharedApplication().statusBarFrame.height) ), animated:true)

1

迅速

您的行= selectioncellRowNumber如果您有=的话,则为您的部分;如果未设置,则为0

//UITableViewScrollPosition.Middle或Bottom或Top

var lastIndex = NSIndexPath(forRow:  selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)

1

这是ScrollTableView的代码以编程方式置顶

迅速:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)


0

如果您想在表格中移动滚动动画,请使用此代码。滚动将在0.5秒内移动到动画顶部。

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

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

[UIView commitAnimations];

0

使用Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.