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

acq*_*sce 131 cocoa-touch objective-c uitableview ios

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

我目前有以下功能

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0];
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
Run Code Online (Sandbox Code Playgroud)

log是一个可变数组,包含构成每个单元格内容的对象.

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

我试图滚动中viewWillAppearviewDidLoad,但在数据尚未加载到表并且都抛出一个异常,这两种情况.

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

Jac*_*kin 146

我相信打电话tableView.setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude), animated: false)会做你想要的.

  • 使用自动布局时不起作用 (71认同)
  • 那是非常感谢你.我创建了一个具有足够高的Y值的CGPoint,这将使它始终显示在底部.一旦视图加载,我可以使用(self.table.contentSize.height - self.table.frame.size.height)以相同的方法移动到底部 (14认同)
  • 虽然这是完美的答案,因为我们不需要计算多少单元格,tableview等的高度.但是我会指出我们需要在重新加载tableview之前调用它...如果不行我们在`[table reloadData]之后写这个;`* (8认同)
  • 哎呀!!!让桌子消失:-o。最好使用 [self.tablescrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottomanimated:NO]; (6认同)
  • 不适用于 ios 10-12 - 表格第一次消失 (4认同)
  • 或者只是滚动到`CGPoint(x:0,y:tableView.contentSize.height)`吗? (2认同)

Osa*_*ias 121

Jacob的回答中,这是代码:

- (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];
    }
}
Run Code Online (Sandbox Code Playgroud)


Cha*_*ndo 121

我认为最简单的方法是:

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

Swift 3版本:

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

  • 单元格比UITableView高吗?从来没有听说过这样的用例。 (3认同)
  • 如果单元格比UITableView高,则不起作用 (2认同)

Han*_*One 41

如果您需要滚动到内容的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];
}
Run Code Online (Sandbox Code Playgroud)

  • 使用autolayout,但是从viewDidLayoutSubviews调用此方法很重要 (7认同)
  • @Unheilig如果要滚动到`self.tableView.contentSize.height`,表视图的内容可能不可见,因为您在内容下滚动.因此,您必须滚动到表视图末尾上方的一个"可见表视图间隙". (3认同)

Raf*_*fAl 31

我正在使用autolayout,但没有一个答案适合我.这是我最终解决的解决方案:

@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)];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这在ios 10中不起作用 - 只显示一个黑色背景的表格 (2认同)
  • 在设置初始内容偏移量时,我使用的是contentSize.height-frame.height + contentInset.bottom,而不是使用CGFLOAT_MAX。使用`CGFLOAT_MAX`似乎让我感到困惑。 (2认同)

ma1*_*w28 23

通过@JacobRelkin接受的解决方案并没有为我在的iOS 7.0中使用自动布局工作.

我有一个自定义子类,UIViewController并添加了一个实例变量_tableView作为其子视图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];
    }
}
Run Code Online (Sandbox Code Playgroud)

[self tableViewScrollToBottomAnimated:NO]viewDidLoad作品结束时打电话.不幸的是,它也导致tableView:heightForRowAtIndexPath:每个细胞被调用三次.


Rya*_*bin 23

这是我在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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这比使用内容大小更好.对于Swift3.if self.numberOfRows(inSection:0)> 0 {self.scrollToRow(at:IndexPath.init(row:self.numberOfRows(inSection:0)-1,section:0),at:.bottom,animated:animated)} (3认同)

Vas*_*huk 16

细节

xCode 8.3.2,swift 3.1

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

tableView.scrollToBottom(animated: true)
Run Code Online (Sandbox Code Playgroud)


Xco*_*OOB 15

实际上,在swift中执行它的"Swifter"方式是:

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

工作对我来说很完美.


T.J*_*.J. 9

我希望表格加载到框架中显示的表格的末尾.我找到了使用

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

没有用,因为当桌面高度小于框架高度时它会出错.请注意,我的表只有一个部分.

对我有用的解决方案是在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];
    }
}
Run Code Online (Sandbox Code Playgroud)

BOOL ivar initialLoad在viewDidLoad中设置为TRUE.


Seg*_*gev 9

对于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)
}
Run Code Online (Sandbox Code Playgroud)


Erp*_*put 5

你应该使用UITableViewScrollPositionBottom.


Irs*_*shi 5

对于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)
}
Run Code Online (Sandbox Code Playgroud)

  • 这不回答OP问题,这是从一开始就有效的.你也应该调用super.viewDidAppear (3认同)