【问题标题】:UITableView - scroll to the topUITableView - 滚动到顶部
【发布时间】:2010-10-18 00:22:37
【问题描述】:

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

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

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

还有其他方法可以滚动到表格视图的顶部吗?

【问题讨论】:

    标签: ios uitableview


    【解决方案1】:

    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)
    

    【讨论】:

    • 我先用CGRectZero试试这个,相当于CGRectMake(0, 0, 0, 0)。这不起作用,但奇怪的是上面的。我想它需要一个正的宽度和高度。谢谢。
    • 注意,如果您在 scrollToRowAtIndexPath: 中运行它,您将需要 animated:NO 以使表格从正确的位置开始。希望对您有所帮助!
    • @hasan83 CGRectMake(0, 0, 0, 0) 或 CGRectZero 不是可见的矩形。我还要说 [mainTableView setContentOffset:CGPointZero animated:YES];是更漂亮的表达方式。
    • 有人注意到在 iOS11 中这一切都被破坏并且在某些情况下无法正确滚动吗?
    • @PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true) 似乎适用于 iOS 11
    【解决方案2】:

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

    我更喜欢

    [mainTableView setContentOffset:CGPointZero animated:YES];
    

    如果您的表格视图中有顶部插图,则必须减去它:

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

    【讨论】:

    • 番茄,番茄。嗯……这在书面上不是很清楚。
    • 当您有表格页眉或页脚视图并希望它们也包含在内时,这是最好的方法。
    • 这确实是一个清晰的代码,但是当您的tableView 顶部有非零contentInset 时,它不起作用。例如:tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);。如果是这种情况,在您的代码中 tableView 滚动到 (0.0f, 5.0f)
    • 我之前评论的解决方法:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
    • 在 iOS 11 上,您应该考虑改用 -scrollView.adjustedContentInset.top
    【解决方案3】:

    可能的行动:

    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
    • 优秀的总结。当您有节标题时,您必须使用 option4 scrollToHeader。
    • 有没有办法向上滚动到 Tableview 上方的搜索栏?
    【解决方案4】:

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

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

    希望这会有所帮助。

    【讨论】:

    • 自 iOS 11 起不再有效。
    【解决方案5】:

    斯威夫特 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)
    

    【讨论】:

    • 如果你的 tableView 中有一个 tableHeaderView 并且它是内联的(随内容滚动)
    • 我有一个普通的和一个UITableViewStyleGrouped(标题随内容滚动),这段代码有效。确保您在主线程中,并在视图出现后启动此代码 (viewDidAppear)。如果您仍然有问题,请尝试将代码放入:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
    • 谢谢。它会带你到第一个牢房。但是,它不显示表格视图标题。
    • 如果tableView由于某种原因为空(0行0部分中没有单元格),这将失败
    【解决方案6】:

    在 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)
    }
    

    【讨论】:

    • 它有时可能不起作用,除非您将该代码包含在 tableView.beginUpdates() 和 tableView.endUpdates() 中。在此之后,我的滚动始终有效。
    【解决方案7】:

    我遇到了调用在空的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
    

    【讨论】:

    • 这不考虑任何表头或节头。
    【解决方案8】:

    不要使用

     tableView.setContentOffset(.zero, animated: true)
    

    它有时会错误地设置偏移量。例如,在我的例子中,单元格实际上略高于带有安全区域插图的视图。不好。

    替代使用

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

    【讨论】:

    • 完美解决方案。
    • 这些解决方案均无效。第一个在 iOS 11 或更高版本下不起作用。如果表格视图有表格标题或第一部分有部分标题,则第二个不起作用,除非您确实希望第一行位于顶部并且不关心显示任何标题。
    • @rmaddy 最好的解决方案是什么?
    【解决方案9】:

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

    考虑到内容插入会产生这种情况:

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

    【讨论】:

    • 谢谢,我一直将其设置为 CGPointZero,无法理解为什么会这样。
    • 自 iOS 11 起不再有效。
    【解决方案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)。干杯!
    • 这段代码对于让部分滚动到顶部非常有用
    【解决方案11】:

    Swift 5、iOS 13

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

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

    如果您正在处理动画(如键盘)或某些异步任务,则尤其如此 - 其他答案通常会滚动到 几乎 底部。如果由于某种原因这并没有让你一直走到底部,那几乎可以肯定是因为一个竞争动画,所以解决方法是将这个动画分派到主队列的末尾:

    DispatchQueue.main.async {
        let last = IndexPath(row: self.someArray.count - 1, section: 0)
        self.tableView.scrollToRow(at: last, at: .bottom, animated: true)
    }
    

    这似乎是多余的,因为您已经在主队列中,但这并不是因为它序列化了动画。

    【讨论】:

    • 你还需要检查是否有section
    • 只要您的 tableView 中没有零行,它就可以工作。否则,我建议使用@catlan's answer
    • @craft 如果您的表格中有零行,那么您不应该尝试滚动到底部,因为它已经存在了。
    • @bsod 感谢您的回复。我确实有一个相关的案例。我正在使用节标题但没有行滚动回顶部。另外,我认为问题是关于top 而不是bottom
    【解决方案12】:

    斯威夫特:

    tableView.setContentOffset(CGPointZero, animated: true)
    

    【讨论】:

    • 自 iOS 11 起不再有效。
    【解决方案13】:

    斯威夫特 3

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

    如果tableView.setContentOffset 不起作用。

    用途:

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

    【讨论】:

    • 这对 iOS 11 或更高版本无效。
    • 感谢提及 beginUpdates() 和 endUpdates()
    【解决方案14】:

    由于我的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)
    }
    

    【讨论】:

    • 这对我更有用
    • 很好的答案,不胜感激
    【解决方案15】:

    除了已经说过的内容之外,您还可以创建一个扩展 (Swift) 或类别 (Objective C),以便将来更容易做到这一点:

    斯威夫特:

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

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

    tableView.scrollToTop(animated: true)
    

    【讨论】:

    • 自 iOS 11 起不再有效。
    【解决方案16】:

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

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

    【讨论】:

    • 自 iOS 11 起不再有效。
    【解决方案17】:

    斯威夫特:

    如果你没有 tableView 标题:

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

    如果是这样:

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

    【讨论】:

      【解决方案18】:

      这是我用来在 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)
          }
      }
      

      【讨论】:

        【解决方案19】:

        在 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()
        

        【讨论】:

        • 1.这在 Swift 4 中也有效。 2. 如果有表头或节头,这不起作用。
        【解决方案20】:

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

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

        【讨论】:

        • 如果有表头或节头,这将不起作用。
        【解决方案21】:

        这是唯一对我有用的代码 sn-p

        斯威夫特 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)
        

        附: 70 是我的标题和表格视图单元格的高度

        【讨论】:

        • 这与滚动到顶部的正确方法相去甚远。仅使用三个单独的行来设置内容偏移量是没有意义的。只需要最后一行,但硬编码特定偏移量不是正确的解决方案。
        【解决方案22】:
        func scrollToTop() {
                NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
                [tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
        }
        

        在任何你想要 UITableView 滚动到顶部的地方调用这个函数

        【讨论】:

          【解决方案23】:

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

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

          【讨论】:

          • 这在 iOS 11 中无效。
          【解决方案24】:

          我使用 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
                      }
                  }
          
              }
          
          }
          

          【讨论】:

            【解决方案25】:

            我必须将 -1 * 的乘积加到状态栏和导航栏的总和中,因为它已经超出了屏幕的那个高度,

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

            【讨论】:

              【解决方案26】:

              迅速

              你的行 = selectioncellRowNumber 你的部分如果你有 = selectionNumber 如果你没有设置是零

              //UITableViewScrollPosition.Middle or Bottom or Top

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

              【讨论】:

                【解决方案27】:

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

                斯威夫特:

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

                【讨论】:

                  【解决方案28】:

                  在 Swift-3 中:

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

                  【讨论】:

                    【解决方案29】:

                    如果您想在表格中移动滚动动画,请使用此代码。滚动在 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];
                    

                    【讨论】:

                      【解决方案30】:

                      使用 Swift:

                      self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
                      

                      【讨论】:

                        猜你喜欢
                        • 2018-11-02
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-10-04
                        • 2016-09-04
                        • 1970-01-01
                        • 2014-10-20
                        • 2013-03-24
                        • 2015-06-01
                        相关资源
                        最近更新 更多