UITableView - scroll to the top

IosUitableview

Ios Problem Overview


In my table view I have to scroll to the top. But I cannot guarantee that the first object is going to be section 0, row 0. May be that my table view will start from section number 5.

So I get an exception, when I call:

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

Is there another way to scroll to the top of table view?

Ios Solutions


Solution 1 - Ios

UITableView is a subclass of UIScrollView, so you can also use:

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

Or

[mainTableView setContentOffset:CGPointZero animated:YES];

And in Swift:

mainTableView.setContentOffset(CGPointZero, animated:true)

And in Swift 3 & above:

mainTableView.setContentOffset(.zero, animated: true)

Solution 2 - Ios

Note: This answer isn't valid for iOS 11 and later.

I prefer

[mainTableView setContentOffset:CGPointZero animated:YES];

If you have a top inset on your table view, you have to subtract it:

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

Solution 3 - Ios

Possible Actions:

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

Disable Scroll To Top:

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

Modify and use it as per requirement.

Swift 4

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

Solution 4 - Ios

It's better to not use NSIndexPath (empty table), nor assume that top point is CGPointZero (content insets), that's what I use -

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

Hope this helps.

Solution 5 - Ios

Swift 4:

This works very well:

//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)

Solution 6 - Ios

On iOS 11, use adjustedContentInset to correctly scroll to top for both cases when the in-call status bar is visible or not.

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

Swift:

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

Solution 7 - Ios

I've encountered an issue calling trying some of the methods on an empty tableView. Here's another option for Swift 4 that handles empty tableviews.

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

Usage:

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

Solution 8 - Ios

DONT USE

 tableView.setContentOffset(.zero, animated: true)

It can sometimes set the offset improperly. For example, in my case, the cell was actually slightly above the view with safe area insets. Not good.

INSTEAD USE

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

Solution 9 - Ios

For tables that have a contentInset, setting the content offset to CGPointZero will not work. It'll scroll to the content top vs. scrolling to the table top.

Taking content inset into account produces this instead:

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

Solution 10 - Ios

This code let's you scroll a specific section to top

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

Solution 11 - Ios

Swift 5, iOS 13

I know this question already has a lot of answers but from my experience this method always works:

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

And this is especially true if you're working with animations (like keyboard) or certain async tasks—the other answers will often scroll to the almost bottom. If for some reason this doesn't get you all the way to the bottom, it's almost certainly because of a competing animation so the workaround is to dispatch this animation to the end of the main queue:

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

This may seem redundant since you're already on the main queue but it's not because it serializes the animations.

Solution 12 - Ios

Swift:

tableView.setContentOffset(CGPointZero, animated: true)

Solution 13 - Ios

Swift 3

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

if tableView.setContentOffset don't work.

Use:

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

Solution 14 - Ios

Adding on to what's already been said, you can create a extension (Swift) or category (Objective C) to make this easier in the future:

Swift:

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

Any time you want to scroll any given tableView to the top you can call the following code:

tableView.scrollToTop(animated: true)

Solution 15 - Ios

Since my tableView is full of all kinds of insets, this was the only thing that worked well:

Swift 3

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

Swift 2

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

Solution 16 - Ios

I prefer the following, as it takes into account an inset. If there is no inset, it will still scroll to the top as the inset will be 0.

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

Solution 17 - Ios

Swift :

if you don't have tableView header :

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

if so :

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

Solution 18 - Ios

Here's what I use to work correctly on 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)
    }
}

Solution 19 - Ios

In Swift 5 , Thanks @Adrian's answer a lot

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

Usage:

tableView.scrollToTop()

Solution 20 - Ios

using contentOffset is not the right way. this would be better as it is table view's natural way

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

Solution 21 - Ios

This was the only code snippet that worked for me

Swift 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)

P.S. 70 is the height of my header and table view cell

Solution 22 - Ios

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

call this function wherever you want UITableView scroll to top

Solution 23 - Ios

Swift 4 via extension, handles empty table view:

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

Solution 24 - Ios

I use tabBarController and i have a few section in my tableview at every tab, so this is best solution for me.

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

Solution 25 - Ios

in swift

your row = selectioncellRowNumber your section if you have = selectionNumber if you dont have set is to zero

//UITableViewScrollPosition.Middle or Bottom or Top

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

Solution 26 - Ios

I had to add the multiply by -1 * to the sum of the status bar and the navigation bar, because it was going that height off the screen,

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

Solution 27 - Ios

Here Is The Code To ScrollTableView To Top Programatically

Swift:

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

Solution 28 - Ios

In Swift-3 :

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

Solution 29 - Ios

If you i would like move scroll animation in the table, use this code. The scroll move to top with animation in .5 seconds.

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    
[_tableContent scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
    
[UIView commitAnimations];

Solution 30 - Ios

With Swift:

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

Solution 31 - Ios

To have a completion when finished, add this extension

// MARK: - UIScrollView

extension UIScrollView {
    
    /// Animate scroll to top with completion
    ///
    /// - Parameters:
    ///   - duration:   TimeInterval
    ///   - completion: Completion block
    func animateScrollToTop(withDuration duration:  TimeInterval,
                            completion:             @escaping (()->())) {
        
        UIView.animate(withDuration: duration, animations: { [weak self] in
                self?.setContentOffset(CGPoint.zero, animated: false)
            }, completion: { finish in
                guard finish else {
                    return
                }
                completion()
        })
    }
}

tableView.animateScrollToTop(withDuration: 0.25) { 
    // Finish
}

Solution 32 - Ios

Here is a simple example of UIScrollView extension that you can use everywhere in your app.

  1. First you should create enum with possible scroll directions:

    enum ScrollDirection { case top, right, bottom, left

     func contentOffsetWith(_ scrollView: UIScrollView) -> CGPoint {
         var contentOffset = CGPoint.zero
         switch self {
             case .top:
                 contentOffset = CGPoint(x: 0, y: -scrollView.contentInset.top)
             case .right:
                 contentOffset = CGPoint(x: scrollView.contentSize.width - scrollView.bounds.size.width, y: 0)
             case .bottom:
                 contentOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
             case .left:
                 contentOffset = CGPoint(x: -scrollView.contentInset.left, y: 0)
             }
         return contentOffset
     }
    

    }

  2. Then add extension to UIScrollView:

    extension UIScrollView { func scrollTo(direction: ScrollDirection, animated: Bool = true) { self.setContentOffset(direction.contentOffsetWith(self), animated: animated) } }

  3. Thats it! Now you can use it:

    myScrollView.scrollTo(.top, animated: false)

This scroll bind to the tableView's content size and it looks more natural than scroll to CGPoint.zero

Solution 33 - Ios

If you need use Objective-C or you still in love:

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

Solution 34 - Ios

Solution with scrollToRow which fixes the problem for empty TableView (needs for search).

import UIKit

extension UITableView {
    
    public func scrollToTop(animated: Bool = false) {
        if numberOfRows(inSection: 0) > 0 {
            scrollToRow(
                at: .init(row: 0, section: 0),
                at: .top,
                animated: animated
            )
        }
    }
    
}

Solution 35 - Ios

The easiest way that I found to force UITableViewController to scroll-to-the-top under iPhone, iPad and macCatalyst (macOS) is as follows:

  • prepare to return 0 from [tableView:numberOfRowsInSection:]
  • call [self.tableView reloadData]
  • call [self.tableView layoutIfNeeded]
  • prepare to return the factual row count from [tableView:numberOfRowsInSection:]
  • call [self.tableView reloadData]

Solution 36 - Ios

Use this code for UITableview implementation in swift:

var cell = tableView.dequeueReusableCellWithIdentifier(“cell”)
if cell == nil {
    cell = UITableViewCell(style: .Value1, reuseIdentifier: “cell”)
}

Solution 37 - Ios

If you don't want scrolling, you can start and stop the scrolling animation as soon as you start it.

    $('document').ready(function() {
    $("html, body").animate({ scrollTop: 0 }, 500);
    return true;
    });

Also, to animate put values for 'x' and 'y', passing in 0,0 will scroll the page to the top left instantly.

window.scrollTo(x, y);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIlya SuzdalnitskiView Question on Stackoverflow
Solution 1 - IoscatlanView Answer on Stackoverflow
Solution 2 - IosfabbView Answer on Stackoverflow
Solution 3 - IosAlvin GeorgeView Answer on Stackoverflow
Solution 4 - IosKofView Answer on Stackoverflow
Solution 5 - IosAlessandro OrnanoView Answer on Stackoverflow
Solution 6 - IosThanh PhamView Answer on Stackoverflow
Solution 7 - IosAdrianView Answer on Stackoverflow
Solution 8 - IosScottyBladesView Answer on Stackoverflow
Solution 9 - IosEran GoldinView Answer on Stackoverflow
Solution 10 - IosRamesh MutheView Answer on Stackoverflow
Solution 11 - IosliquidView Answer on Stackoverflow
Solution 12 - IosEsqarrouthView Answer on Stackoverflow
Solution 13 - IosKerim KhasbulatovView Answer on Stackoverflow
Solution 14 - IosocwangView Answer on Stackoverflow
Solution 15 - IosbudiDinoView Answer on Stackoverflow
Solution 16 - IosjacobView Answer on Stackoverflow
Solution 17 - IosjmcastelView Answer on Stackoverflow
Solution 18 - IosHans BrendeView Answer on Stackoverflow
Solution 19 - IosdengST30View Answer on Stackoverflow
Solution 20 - IosGulzView Answer on Stackoverflow
Solution 21 - IosjimmyrubyView Answer on Stackoverflow
Solution 22 - IosSayali ShindeView Answer on Stackoverflow
Solution 23 - IosShawnView Answer on Stackoverflow
Solution 24 - IosOkanView Answer on Stackoverflow
Solution 25 - Iosidris yıldızView Answer on Stackoverflow
Solution 26 - IosCarlos.VView Answer on Stackoverflow
Solution 27 - IosKavin Kumar ArumugamView Answer on Stackoverflow
Solution 28 - IosJeni KhantView Answer on Stackoverflow
Solution 29 - IosMatheus VelozaView Answer on Stackoverflow
Solution 30 - IosDhananjay PatilView Answer on Stackoverflow
Solution 31 - IosYannStephView Answer on Stackoverflow
Solution 32 - IosRaman ShyniauskiView Answer on Stackoverflow
Solution 33 - IoshandzelView Answer on Stackoverflow
Solution 34 - Iosuser2168735View Answer on Stackoverflow
Solution 35 - IosGaryView Answer on Stackoverflow
Solution 36 - IosPradnyaView Answer on Stackoverflow
Solution 37 - IosPankaj ManjhiView Answer on Stackoverflow