Uitableview-scroll to the top

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?

转载于:https://stackoverflow.com/questions/724892/uitableview-scroll-to-the-top

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)

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];

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)];

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.

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];

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

Swift:

tableView.setContentOffset(CGPointZero, animated: true)

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)

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];

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)

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)

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)

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

Here Is The Code To ScrollTableView To Top Programatically

Swift:

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

In Swift-3 :

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

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

Use this code for UITableview implementation in swift:

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

With Swift:

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

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)

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
}

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)

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

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() {
    let indexPath = IndexPath(row: 0, section: 0)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
      self.scrollToRow(at: indexPath, at: .top, animated: true)
    }
  }
}

Usage:

// from yourViewController or yourTableViewController
tableView.scrollToTop()

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)

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

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

Swift 4 via extension, handles empty table view:

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

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

    }

}

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