ios 如何在视图出现之前滚动到 iPhone 上 UITableView 的底部
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2770158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to scroll to the bottom of a UITableView on the iPhone before the view appears
提问by acqu13sce
I have a UITableView
that is populated with cells of a variable height. I would like the table to scroll to the bottom when the view is pushed into view.
我有一个UITableView
填充了可变高度的单元格。当视图被推入视图时,我希望表格滚动到底部。
I currently have the following function
我目前有以下功能
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0];
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
log is a mutable array containing the objects that make up the content of each cell.
log 是一个可变数组,其中包含构成每个单元格内容的对象。
The above code works fine in viewDidAppear
however this has the unfortunate side effect of displaying the top of the table when the view first appears and then jumping to the bottom. I would prefer it if the table view
could be scrolled to the bottom before it appears.
上面的代码工作正常,viewDidAppear
但是这有一个不幸的副作用,当视图第一次出现时显示表格的顶部,然后跳到底部。如果table view
可以在它出现之前滚动到底部,我会更喜欢它。
I tried the scroll in viewWillAppear
and viewDidLoad
but in both cases the data has not been loaded into the table yet and both throw an exception.
我试图滚动中viewWillAppear
和viewDidLoad
,但在这两种情况下的数据没有被加载到表并且都抛出异常。
Any guidance would be much appreciated, even if it's just a case of telling me what I have is all that is possible.
任何指导都将不胜感激,即使只是告诉我我所拥有的一切都是可能的。
回答by Jacob Relkin
I believe that calling
我相信呼唤
tableView.setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude), animated: false)
will do what you want.
会做你想做的。
回答by Chamira Fernando
I think the easiest way is this:
我认为最简单的方法是这样的:
if (self.messages.count > 0)
{
[self.tableView
scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1
inSection:0]
atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
Swift 3 Version:
斯威夫特 3 版本:
if messages.count > 0 {
userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true)
}
回答by Osama F Elias
From Jacob's answer, this is the code:
从雅各布的回答,这是代码:
- (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];
}
}
回答by Hans One
If you need to scroll to the EXACT end of the content, you can do it like this:
如果您需要滚动到内容的 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];
}
回答by RaffAl
I'm using autolayout and none of the answers worked for me. Here is my solution that finally worked:
我正在使用自动布局,但没有一个答案对我有用。这是我最终奏效的解决方案:
@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)];
}
}
回答by Ryan Herubin
Here's an extension that I implemented in Swift 2.0. These functions should be called after the tableview
has been loaded:
这是我在 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)
}
}
}
回答by ma11hew28
The accepted solution by @JacobRelkindidn't work for me in iOS 7.0 using Auto Layout.
在通过@JacobRelkin接受的解决方案并没有为我在的iOS 7.0中使用自动布局工作。
I have a custom subclass of UIViewController
and added an instance variable _tableView
as a subview of its view
. I positioned _tableView
using Auto Layout. I tried calling this method at the end of viewDidLoad
and even in viewWillAppear:
. Neither worked.
我有一个自定义子类,UIViewController
并添加了一个实例变量_tableView
作为其view
. 我_tableView
使用自动布局定位。我尝试viewDidLoad
在viewWillAppear:
. 都没有工作。
So, I added the following method to my custom subclass of UIViewController
.
因此,我将以下方法添加到我的自定义子类UIViewController
.
- (void)tableViewScrollToBottomAnimated:(BOOL)animated {
NSInteger numberOfRows = [_tableView numberOfRowsInSection:0];
if (numberOfRows) {
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
}
}
Calling [self tableViewScrollToBottomAnimated:NO]
at the end of viewDidLoad
works. Unfortunately, it also causes tableView:heightForRowAtIndexPath:
to get called three times for every cell.
工作[self tableViewScrollToBottomAnimated:NO]
结束时调用viewDidLoad
。不幸的是,它也会导致tableView:heightForRowAtIndexPath:
每个单元格被调用 3 次。
回答by Vasily Bodnarchuk
Details
细节
- Xcode 8.3.2, swift 3.1
- Xcode 10.2 (10E125), Swift 5
- Xcode 8.3.2,快速 3.1
- Xcode 10.2 (10E125),Swift 5
Code
代码
import UIKit
extension UITableView {
func scrollToBottom(animated: Bool) {
let y = contentSize.height - frame.size.height
if y < 0 { return }
setContentOffset(CGPoint(x: 0, y: y), animated: animated)
}
}
Usage
用法
tableView.scrollToBottom(animated: true)
Full sample
完整样品
Do not forget to paste solution code!
不要忘记粘贴解决方案代码!
import UIKit
class ViewController: UIViewController {
private weak var tableView: UITableView?
private lazy var cellReuseIdentifier = "CellReuseIdentifier"
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView(frame: view.frame)
view.addSubview(tableView)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
self.tableView = tableView
tableView.dataSource = self
tableView.performBatchUpdates(nil) { [weak self] result in
if result { self?.tableView?.scrollToBottom(animated: true) }
}
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath )
cell.textLabel?.text = "\(indexPath)"
return cell
}
}
回答by XcodeNOOB
Actually a "Swifter" way to do it in swift is :
实际上,在 swift 中执行此操作的“更快”方法是:
var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0)
self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
work Perfect for me.
非常适合我。
回答by Segev
For 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)
}