如何知道UITableView在iPhone中何时滚动到底部

时间:2022-08-25 07:52:46

I would like to know when a UITableView did scroll to bottom in order to load and show more content, something like a delegate or something else to let the controller know when the table did scroll to bottom.

我想知道UITableView是什么时候滚动到底部来加载和显示更多内容的,比如委托或者其他什么东西来让控制器知道表格何时滚动到底部。

Does anyone know this, please help me, thanks in advance!

有谁知道这个,请帮助我,提前谢谢!

16 个解决方案

#1


17  

The best way is to test a point at the bottom of the screen and use this method call when ever the user scrolls (scrollViewDidScroll):

最好的方法是测试屏幕底部的一个点,并在用户滚动(scrollViewDidScroll)时使用此方法调用:

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point

Test a point near the bottom of the screen, and then using the indexPath it returns check if that indexPath is the last row then if it is, add rows.

在屏幕底部附近测试一个点,然后使用indexPath返回检查,如果这个indexPath是最后一行,那么添加行。

#2


243  

in the tableview delegate do something like this

在tableview委托中做这样的事情。

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;
    // NSLog(@"offset: %f", offset.y);   
    // NSLog(@"content.height: %f", size.height);   
    // NSLog(@"bounds.height: %f", bounds.size.height);   
    // NSLog(@"inset.top: %f", inset.top);   
    // NSLog(@"inset.bottom: %f", inset.bottom);   
    // NSLog(@"pos: %f of %f", y, h);

    float reload_distance = 10;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}

#3


60  

Modified neoneyes answer a bit.

修改过的新生儿眼回答了一点。

This answer targets those of you who only wants the event to be triggered once per release of the finger.

这个答案针对的是那些只希望在每次手指松开时触发事件一次的人。

Suitable when loading more content from some content provider (web service, core data etc). Note that this approach does not respect the response time from your web service.

适合从某些内容提供者(web服务、核心数据等)加载更多内容。注意,这种方法不尊重web服务的响应时间。

- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
                  willDecelerate:(BOOL)decelerate
{
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;

    float reload_distance = 50;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}

#4


38  

add this method in the UITableViewDelegate:

在UITableViewDelegate中添加此方法:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{   
    CGFloat height = scrollView.frame.size.height;

    CGFloat contentYoffset = scrollView.contentOffset.y;

    CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset;

    if(distanceFromBottom < height) 
    {
        NSLog(@"end of the table");
    }
}

#5


19  

Use – tableView:willDisplayCell:forRowAtIndexPath: (UITableViewDelegate method)

Use - tableView:willDisplayCell:forRowAtIndexPath: (UITableViewDelegate方法)

Simply compare the indexPath with the items in your data array (or whatever data source you use for your table view) to figure out if the last element is being displayed.

只需将indexPath与数据数组中的项(或表视图中使用的任何数据源)进行比较,以确定是否显示了最后一个元素。

Docs: http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:willDisplayCell:forRowAtIndexPath:

文档:http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html / / apple_ref / occ / intfm / UITableViewDelegate / tableView:willDisplayCell:forRowAtIndexPath:

#6


18  

None of the answers above helped me, so I came up with this:

上面的答案没有一个对我有帮助,所以我想到了这个:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{   
    NSArray *visibleRows = [self.tableView visibleCells];
    UITableViewCell *lastVisibleCell = [visibleRows lastObject];
    NSIndexPath *path = [self.tableView indexPathForCell:lastVisibleCell];
    if(path.section == lastSection && path.row == lastRow)
    {
        // Do something here
    }
}

#7


13  

UITableView is a subclass of UIScrollView, and UITableViewDelegate conforms to UIScrollViewDelegate. So the delegate you attach to the table view will get events such as scrollViewDidScroll:, and you can call methods such as contentOffset on the table view to find the scroll position.

UITableView是UIScrollView的子类,UITableViewDelegate符合UIScrollViewDelegate。因此,您附加到表视图的委托将获得诸如scrollViewDidScroll:之类的事件,并且您可以调用表视图上的contentOffset等方法来找到滚动位置。

#8


7  

NSLog(@"%f / %f",tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height);

if (tableView.contentOffset.y == tableView.contentSize.height - tableView.frame.size.height)
        [self doSomething];

Nice and simple

漂亮的和简单的

#9


7  

in Swift you can do something like this. Following condition will be true every time you reach end of the tableview

在Swift中,你可以做这样的事情。当您到达tableview的末尾时,条件将是正确的。

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}

#10


6  

Building on @Jay Mayu's answer, which I felt was one of the better solutions:

基于@Jay Mayu的回答,我觉得这是一个更好的解决方案:

Objective-C

objective - c

// UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

// Need to call the service & update the array
if(indexPath.row + 1 == self.sourceArray.count) {
    DLog(@"Displayed the last row!");
  }
}

Swift 2.x

快2.倍

// UITableViewDelegate
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row + 1) == sourceArray.count {
        print("Displayed the last row!")
    }
}

#11


5  

I generally use this to load more data , when last cell starts display

当最后一个单元格开始显示时,我通常使用它来加载更多的数据

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   if (indexPath.row ==  myDataArray.count-1) {
        NSLog(@"load more");
    }
}

#12


5  

Taking neoneye excellent answers but in swift, and renaming of the variables..

接受neeyeye出色的答案,但迅速,并重命名的变量。

Basically we know we have reached the bottom of the table view if the yOffsetAtBottom is beyond the table content height.

基本上我们知道,如果yOffsetAtBottom超出了表的内容高度,我们已经到达了表视图的底部。

func isTableViewScrolledToBottom() -> Bool {
    let tableHeight = tableView.bounds.size.height
    let contentHeight = tableView.contentSize.height
    let insetHeight = tableView.contentInset.bottom

    let yOffset = tableView.contentOffset.y
    let yOffsetAtBottom = yOffset + tableHeight - insetHeight

    return yOffsetAtBottom > contentHeight
}

#13


5  

Here is the swift 3.0 version code.

以下是swift 3.0版本代码。

   func scrollViewDidScroll(_ scrollView: UIScrollView) {

        let offset = scrollView.contentOffset
        let bounds = scrollView.bounds
        let size = scrollView.contentSize
        let inset = scrollView.contentInset
        let y: Float = Float(offset.y) + Float(bounds.size.height) + Float(inset.bottom)
        let height: Float = Float(size.height)
        let distance: Float = 10

        if y > height + distance {
            // load more data
        }
    }

#14


3  

My solution is to add cells before tableview will decelerate on estimated offset. It's predictable on by velocity.

我的解决方案是在tableview会在估计的偏移量上减速之前添加单元格。它的速度是可以预测的。

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)offset {

    NSLog(@"offset: %f", offset->y+scrollView.frame.size.height);
    NSLog(@"Scroll view content size: %f", scrollView.contentSize.height);

    if (offset->y+scrollView.frame.size.height > scrollView.contentSize.height - 300) {
        NSLog(@"Load new rows when reaches 300px before end of content");
        [[DataManager shared] fetchRecordsNextPage];
    }
}

#15


3  

Update for Swift 3

更新快3

Neoneye's answer worked best for me in Objective C, this is the equivalent of the answer in Swift 3:

在Objective C中,Neoneye的回答对我来说效果最好,相当于Swift 3中的回答:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let offset: CGPoint = scrollView.contentOffset
    let bounds: CGRect = scrollView.bounds
    let size: CGSize = scrollView.contentSize
    let inset: UIEdgeInsets = scrollView.contentInset
    let y: CGFloat = offset.y + bounds.size.height - inset.bottom
    let h: CGFloat = size.height
//        print("offset: %f", offset.y)
//        print("content.height: %f", size.height)
//        print("bounds.height: %f", bounds.size.height)
//        print("inset.top: %f", inset.top)
//        print("inset.bottom: %f", inset.bottom)
//        print("position: %f of %f", y, h)

    let reloadDistance: CGFloat = 10

    if (y > h + reloadDistance) {
            print("load more rows")
    }
}

#16


2  

I want perform some action on my any 1 full Tableviewcell.

我想对任意1个全Tableviewcell执行一些操作。

So the code is link the :

所以代码是链接:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray* cells = self.tableView.visibleCells;
    NSIndexPath *indexPath = nil ;

    for (int aIntCount = 0; aIntCount < [cells count]; aIntCount++)
    {

        UITableViewCell *cell = [cells objectAtIndex:aIntCount];
CGRect cellRect = [self.tableView convertRect:cell.frame toView:self.tableView.superview];

        if (CGRectContainsRect(self.tableView.frame, cellRect))
        {
            indexPath = [self.tableView indexPathForCell:cell];

    //  remain logic
        }
     }
}

May this is help to some one.

愿这对某一个人有所帮助。

#1


17  

The best way is to test a point at the bottom of the screen and use this method call when ever the user scrolls (scrollViewDidScroll):

最好的方法是测试屏幕底部的一个点,并在用户滚动(scrollViewDidScroll)时使用此方法调用:

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point

Test a point near the bottom of the screen, and then using the indexPath it returns check if that indexPath is the last row then if it is, add rows.

在屏幕底部附近测试一个点,然后使用indexPath返回检查,如果这个indexPath是最后一行,那么添加行。

#2


243  

in the tableview delegate do something like this

在tableview委托中做这样的事情。

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;
    // NSLog(@"offset: %f", offset.y);   
    // NSLog(@"content.height: %f", size.height);   
    // NSLog(@"bounds.height: %f", bounds.size.height);   
    // NSLog(@"inset.top: %f", inset.top);   
    // NSLog(@"inset.bottom: %f", inset.bottom);   
    // NSLog(@"pos: %f of %f", y, h);

    float reload_distance = 10;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}

#3


60  

Modified neoneyes answer a bit.

修改过的新生儿眼回答了一点。

This answer targets those of you who only wants the event to be triggered once per release of the finger.

这个答案针对的是那些只希望在每次手指松开时触发事件一次的人。

Suitable when loading more content from some content provider (web service, core data etc). Note that this approach does not respect the response time from your web service.

适合从某些内容提供者(web服务、核心数据等)加载更多内容。注意,这种方法不尊重web服务的响应时间。

- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
                  willDecelerate:(BOOL)decelerate
{
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;

    float reload_distance = 50;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}

#4


38  

add this method in the UITableViewDelegate:

在UITableViewDelegate中添加此方法:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{   
    CGFloat height = scrollView.frame.size.height;

    CGFloat contentYoffset = scrollView.contentOffset.y;

    CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset;

    if(distanceFromBottom < height) 
    {
        NSLog(@"end of the table");
    }
}

#5


19  

Use – tableView:willDisplayCell:forRowAtIndexPath: (UITableViewDelegate method)

Use - tableView:willDisplayCell:forRowAtIndexPath: (UITableViewDelegate方法)

Simply compare the indexPath with the items in your data array (or whatever data source you use for your table view) to figure out if the last element is being displayed.

只需将indexPath与数据数组中的项(或表视图中使用的任何数据源)进行比较,以确定是否显示了最后一个元素。

Docs: http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:willDisplayCell:forRowAtIndexPath:

文档:http://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html / / apple_ref / occ / intfm / UITableViewDelegate / tableView:willDisplayCell:forRowAtIndexPath:

#6


18  

None of the answers above helped me, so I came up with this:

上面的答案没有一个对我有帮助,所以我想到了这个:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{   
    NSArray *visibleRows = [self.tableView visibleCells];
    UITableViewCell *lastVisibleCell = [visibleRows lastObject];
    NSIndexPath *path = [self.tableView indexPathForCell:lastVisibleCell];
    if(path.section == lastSection && path.row == lastRow)
    {
        // Do something here
    }
}

#7


13  

UITableView is a subclass of UIScrollView, and UITableViewDelegate conforms to UIScrollViewDelegate. So the delegate you attach to the table view will get events such as scrollViewDidScroll:, and you can call methods such as contentOffset on the table view to find the scroll position.

UITableView是UIScrollView的子类,UITableViewDelegate符合UIScrollViewDelegate。因此,您附加到表视图的委托将获得诸如scrollViewDidScroll:之类的事件,并且您可以调用表视图上的contentOffset等方法来找到滚动位置。

#8


7  

NSLog(@"%f / %f",tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height);

if (tableView.contentOffset.y == tableView.contentSize.height - tableView.frame.size.height)
        [self doSomething];

Nice and simple

漂亮的和简单的

#9


7  

in Swift you can do something like this. Following condition will be true every time you reach end of the tableview

在Swift中,你可以做这样的事情。当您到达tableview的末尾时,条件将是正确的。

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}

#10


6  

Building on @Jay Mayu's answer, which I felt was one of the better solutions:

基于@Jay Mayu的回答,我觉得这是一个更好的解决方案:

Objective-C

objective - c

// UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

// Need to call the service & update the array
if(indexPath.row + 1 == self.sourceArray.count) {
    DLog(@"Displayed the last row!");
  }
}

Swift 2.x

快2.倍

// UITableViewDelegate
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row + 1) == sourceArray.count {
        print("Displayed the last row!")
    }
}

#11


5  

I generally use this to load more data , when last cell starts display

当最后一个单元格开始显示时,我通常使用它来加载更多的数据

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   if (indexPath.row ==  myDataArray.count-1) {
        NSLog(@"load more");
    }
}

#12


5  

Taking neoneye excellent answers but in swift, and renaming of the variables..

接受neeyeye出色的答案,但迅速,并重命名的变量。

Basically we know we have reached the bottom of the table view if the yOffsetAtBottom is beyond the table content height.

基本上我们知道,如果yOffsetAtBottom超出了表的内容高度,我们已经到达了表视图的底部。

func isTableViewScrolledToBottom() -> Bool {
    let tableHeight = tableView.bounds.size.height
    let contentHeight = tableView.contentSize.height
    let insetHeight = tableView.contentInset.bottom

    let yOffset = tableView.contentOffset.y
    let yOffsetAtBottom = yOffset + tableHeight - insetHeight

    return yOffsetAtBottom > contentHeight
}

#13


5  

Here is the swift 3.0 version code.

以下是swift 3.0版本代码。

   func scrollViewDidScroll(_ scrollView: UIScrollView) {

        let offset = scrollView.contentOffset
        let bounds = scrollView.bounds
        let size = scrollView.contentSize
        let inset = scrollView.contentInset
        let y: Float = Float(offset.y) + Float(bounds.size.height) + Float(inset.bottom)
        let height: Float = Float(size.height)
        let distance: Float = 10

        if y > height + distance {
            // load more data
        }
    }

#14


3  

My solution is to add cells before tableview will decelerate on estimated offset. It's predictable on by velocity.

我的解决方案是在tableview会在估计的偏移量上减速之前添加单元格。它的速度是可以预测的。

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)offset {

    NSLog(@"offset: %f", offset->y+scrollView.frame.size.height);
    NSLog(@"Scroll view content size: %f", scrollView.contentSize.height);

    if (offset->y+scrollView.frame.size.height > scrollView.contentSize.height - 300) {
        NSLog(@"Load new rows when reaches 300px before end of content");
        [[DataManager shared] fetchRecordsNextPage];
    }
}

#15


3  

Update for Swift 3

更新快3

Neoneye's answer worked best for me in Objective C, this is the equivalent of the answer in Swift 3:

在Objective C中,Neoneye的回答对我来说效果最好,相当于Swift 3中的回答:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let offset: CGPoint = scrollView.contentOffset
    let bounds: CGRect = scrollView.bounds
    let size: CGSize = scrollView.contentSize
    let inset: UIEdgeInsets = scrollView.contentInset
    let y: CGFloat = offset.y + bounds.size.height - inset.bottom
    let h: CGFloat = size.height
//        print("offset: %f", offset.y)
//        print("content.height: %f", size.height)
//        print("bounds.height: %f", bounds.size.height)
//        print("inset.top: %f", inset.top)
//        print("inset.bottom: %f", inset.bottom)
//        print("position: %f of %f", y, h)

    let reloadDistance: CGFloat = 10

    if (y > h + reloadDistance) {
            print("load more rows")
    }
}

#16


2  

I want perform some action on my any 1 full Tableviewcell.

我想对任意1个全Tableviewcell执行一些操作。

So the code is link the :

所以代码是链接:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray* cells = self.tableView.visibleCells;
    NSIndexPath *indexPath = nil ;

    for (int aIntCount = 0; aIntCount < [cells count]; aIntCount++)
    {

        UITableViewCell *cell = [cells objectAtIndex:aIntCount];
CGRect cellRect = [self.tableView convertRect:cell.frame toView:self.tableView.superview];

        if (CGRectContainsRect(self.tableView.frame, cellRect))
        {
            indexPath = [self.tableView indexPathForCell:cell];

    //  remain logic
        }
     }
}

May this is help to some one.

愿这对某一个人有所帮助。