如何在视图出现之前滚动到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
可以滚动到底部之前,我会更喜欢它。
我在viewWillAppear
和viewDidLoad
尝试了滚动,但是在这两种情况下,数据还没有被加载到表中,并且都抛出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)