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