如何在视图出现之前滚动到iPhone上的UITableView的底部

我有一个UITableView填充可变高度的单元格。 当视图被推入视图时,我希望表格滚动到底部。

我目前有以下function

 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0]; [self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 

日志是一个可变数组,其中包含组成每个单元格内容的对象。

上面的代码在viewDidAppear中工作正常,但是当视图第一次出现然后跳到底部时,这具有显示表顶部的viewDidAppear副作用。 如果table view可以滚动到底部之前,我会更喜欢它。

我在viewWillAppearviewDidLoad尝试了滚动,但是在这两种情况下,数据还没有被加载到表中,并且都抛出exception。

任何指导都会非常感激,即使只是告诉我我所拥有的一切都是可能的。

我相信调用[table setContentOffset:CGPointMake(0, CGFLOAT_MAX)]将做你想要的。

从雅各布的答案 ,这是代码:

 - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (self.messagesTableView.contentSize.height > self.messagesTableView.frame.size.height) { CGPoint offset = CGPointMake(0, self.messagesTableView.contentSize.height - self.messagesTableView.frame.size.height); [self.messagesTableView setContentOffset:offset animated:YES]; } } 

我觉得最简单的方法是这样的:

 if (self.messages.count > 0) { [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 

Swift 3版本:

 if messages.count > 0 { userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true) } 

如果您需要滚动到内容的EXACT末尾,可以这样做:

 - (void)scrollToBottom { CGFloat yOffset = 0; if (self.tableView.contentSize.height > self.tableView.bounds.size.height) { yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height; } [self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO]; } 

我使用自动布局,没有答案为我工作。 这是我的解决scheme,终于奏效了:

 @property (nonatomic, assign) BOOL shouldScrollToLastRow; - (void)viewDidLoad { [super viewDidLoad]; _shouldScrollToLastRow = YES; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Scroll table view to the last row if (_shouldScrollToLastRow) { _shouldScrollToLastRow = NO; [self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; } } 

@JacobRelkin接受的解决scheme在iOS 7.0中不适用于我使用自动布局。

我有一个UIViewController的自定义子类,并添加一个实例variables_tableView作为其view的子view 。 我使用自动布局来定位_tableView 。 我试图在viewDidLoad结尾调用这个方法,甚至在viewWillAppear: 。 都没有工作。

所以,我将下面的方法添加到我的UIViewController自定义子类。

 - (void)tableViewScrollToBottomAnimated:(BOOL)animated { NSInteger numberOfRows = [_tableView numberOfRowsInSection:0]; if (numberOfRows) { [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated]; } } 

viewDidLoad的末尾调用[self tableViewScrollToBottomAnimated:NO] 。 不幸的是,它也会导致tableView:heightForRowAtIndexPath:为每个单元tableView:heightForRowAtIndexPath:三次。

这是我在Swift 2.0中实现的一个扩展。 这些函数应该在tableview被加载后调用:

 import UIKit extension UITableView { func setOffsetToBottom(animated: Bool) { self.setContentOffset(CGPointMake(0, self.contentSize.height - self.frame.size.height), animated: true) } func scrollToLastRow(animated: Bool) { if self.numberOfRowsInSection(0) > 0 { self.scrollToRowAtIndexPath(NSIndexPath(forRow: self.numberOfRowsInSection(0) - 1, inSection: 0), atScrollPosition: .Bottom, animated: animated) } } } 

其实一个“快捷”的方法是迅速做到这一点:

 var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0) self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true) 

工作适合我。

细节

xCode 8.3.2,swift 3.1

 import UIKit extension UITableView { func scrollToBottom(animated: Bool) { let y = contentSize.height - frame.size.height setContentOffset(CGPoint(x: 0, y: (y<0) ? 0 : y), animated: animated) } } 

用法

 tableView.scrollToBottom(animated: true) 

我想要加载表格中显示的表格的末尾。 我发现使用

 NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 

没有工作,因为当表格高度小于框架高度时出现错误。 注意我的表只有一个部分。

为我工作的解决scheme是在viewWillAppear中实现以下代码:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // on the initial cell load scroll to the last row (ie the latest Note) if (initialLoad==TRUE) { initialLoad=FALSE; NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; CGPoint offset = CGPointMake(0, (1000000.0)); [self.tableView setContentOffset:offset animated:NO]; } } 

BOOL ivar initialLoad在viewDidLoad中设置为TRUE。

对于Swift:

 if tableView.contentSize.height > tableView.frame.size.height { let offset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.size.height) tableView.setContentOffset(offset, animated: false) } 

您应该使用UITableViewScrollPositionBottom来代替。

当然是一个Bug。 可能在代码中的某处使用table.estimatedRowHeight = value (例如100)。 将此值replace为您认为行高可以达到的最高值 ,例如500 ..这应该结合以下代码解决问题:

 //auto scroll down example let delay = 0.1 * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue(), { self.table.scrollToRowAtIndexPath(NSIndexPath(forRow: self.Messages.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false) }) 

对于Swift 3(Xcode 8.1):

 override func viewDidAppear(_ animated: Bool) { let numberOfSections = self.tableView.numberOfSections let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1) let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true) } 

使用上面的解决scheme,这将滚动到您的表的底部(只有在第一次加载表内容):

 //Scroll to bottom of table CGSize tableSize = myTableView.contentSize; [myTableView setContentOffset:CGPointMake(0, tableSize.height)]; 

经过很多的摆弄这是什么对我有用:

 var viewHasAppeared = false override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if !viewHasAppeared { goToBottom() } } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) viewHasAppeared = true } private func goToBottom() { guard data.count > 0 else { return } let indexPath = NSIndexPath(forRow: data.count - 1, inSection: 0) tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false) tableView.layoutIfNeeded() } 

关键的结果是没有包装scrollToRowAtIndexPath里面的dispatch_async像一些build议,但只是跟随它调用layoutIfNeeded

我的理解是,在当前线程中调用scroll方法可以保证显示视图之前立即设置滚动偏移量。 当我调度到主线程时,视图在滚动生效前瞬间显示出来。

(还要注意,你需要viewHasAppeared标志,因为每次调用viewDidLayoutSubviews你都不想goToBottom ,例如只要方向改变就会调用它。)

在Swift 3.0中

 self.tableViewFeeds.setContentOffset(CGPoint(x: 0, y: CGFLOAT_MAX), animated: true) 

感谢雅各的答案。 真正有用的,如果有人用monodouch c#版本有趣

 private void SetScrollPositionDown() { if (tblShoppingListItem.ContentSize.Height > tblShoppingListItem.Frame.Size.Height) { PointF offset = new PointF(0, tblShoppingListItem.ContentSize.Height - tblShoppingListItem.Frame.Size.Height); tblShoppingListItem.SetContentOffset(offset,true ); } } 

使用这个简单的代码来滚动tableView底部

 NSInteger rows = [tableName numberOfRowsInSection:0]; if(rows > 0) { [tableName scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 

如果您在向下滚动之前必须asynchronous加载数据,则可以使用以下解决scheme:

 tableView.alpha = 0 // We want animation! lastMessageShown = false // This is ivar viewModel.fetch { [unowned self] result in self.tableView.reloadData() if !self.lastMessageShown { dispatch_async(dispatch_get_main_queue()) { [unowned self] in if self.rowCount > 0 { self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.rowCount, inSection: 0), atScrollPosition: .Bottom, animated: false) } UIView.animateWithDuration(0.1) { self.tableView.alpha = 1 self.lastMessageShown = true // Do it once } } } } 

swift 3上的function滚动到底部

  override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(false) //scroll down if lists.count > 2 { let numberOfSections = self.tableView.numberOfSections let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1) let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true) } } 

在iOS中,这对我来说工作得很好

 CGFloat height = self.inputTableView.contentSize.height; if (height > CGRectGetHeight(self.inputTableView.frame)) { height -= (CGRectGetHeight(self.inputTableView.frame) - CGRectGetHeight(self.navigationController.navigationBar.frame)); } else { height = 0; } [self.inputTableView setContentOffset:CGPointMake(0, height) animated:animated]; 

它需要从viewDidLayoutSubviews调用

[self.tableViewInfo scrollRectToVisible:CGRectMake(0,self.tableViewInfo.contentSize.height-self.tableViewInfo.height,self.tableViewInfo.width,self.tableViewInfo.height)animated:YES];

接受的答案不适用于我的表(数千行,dynamic加载),但下面的代码工作:

 - (void)scrollToBottom:(id)sender { if ([self.sections count] > 0) { NSInteger idx = [self.sections count] - 1; CGRect sectionRect = [self.tableView rectForSection:idx]; sectionRect.size.height = self.tableView.frame.size.height; [self.tableView scrollRectToVisible:sectionRect animated:NO]; } } 

不需要任何滚动,你可以通过使用这个代码来做到这一点:

 [YOURTABLEVIEWNAME setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; 

如果以编程方式为tableview设置框架,请确保正确设置框架。

 func scrollToBottom() { let sections = self.chatTableView.numberOfSections if sections > 0 { let rows = self.chatTableView.numberOfRows(inSection: sections - 1) let last = IndexPath(row: rows - 1, section: sections - 1) DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) } } } 

你应该添加

 DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) } 

或者它不会滚动到底部。

在Swift中,你只需要

 self.tableView.scrollToNearestSelectedRowAtScrollPosition(UITableViewScrollPosition.Bottom, animated: true) 

使其自动滚动到button

在swift 3.0中如果你想要去tableview的任何特定单元格更改单元格索引值就像改变“self.yourArr.count”的值。

 self.yourTable.reloadData() self.scrollToBottom() func scrollToBottom(){ DispatchQueue.global(qos: .background).async { let indexPath = IndexPath(row: self.yourArr.count-1, section: 0) self.tblComment.scrollToRow(at: indexPath, at: .bottom, animated: true) } } 

我相信旧的解决scheme不适用于swift3。

如果您知道表格中的数字行,您可以使用:

 tableView.scrollToRow( at: IndexPath(item: listCountInSection-1, section: sectionCount - 1 ), at: .top, animated: true)