Detecting the bottom "bounce" of UITableView
Asked Answered
S

2

8

I have a table view that performs an animation when the user scrolls down on a UITableView (push thumb up) and a different animation when the user scrolls up (Push thumb down) on a UITableView.

The problem is when the user reaches the bottom of a UITableView and it bounces, the table registers an upward and then downward movement, thus performing the animation when it should not.

This same exact behavior happens when scrolling to the top; however, I am able to detect it like so:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

    self.lastContentOffset = scrollView.contentOffset;

}


-(void) scrollViewDidScroll:(UIScrollView *)scrollView {

    // Check if we are at the top of the table
    // This will stop animation when tableview bounces

    if(self.tableView.contentOffset.y < 0){
        // Dont animate, top of tableview bounce


    } else {

        CGPoint currentOffset = scrollView.contentOffset;

        if (currentOffset.y > self.lastContentOffset.y) {

            // Downward animation
            [self animate:@"Down"];

        } else {

            // Upward
            [self animate:@"Up"];

        }

        self.lastContentOffset = currentOffset;

    }

}

This works perfectly, but for the life of me I cannot figure out an if condition to detect the bottom as well. I am sure it is simple and I just cant figure it out.

Smoothspoken answered 12/8, 2013 at 16:7 Comment(0)
S
36

How about something like this:

if (self.tableView.contentOffset.y >= (self.tableView.contentSize.height - self.tableView.bounds.size.height)) 
{
    // Don't animate
}
Silda answered 12/8, 2013 at 16:27 Comment(3)
That's it! I could have sworn I tried that, but it is very possible I messed up my operators. Thanks a lot!Smoothspoken
You need to account for contentInset. If set to something greater than zero, this will not work. Use this instead: if (self.tableView.contentOffset.y - self.tableView.contentInset.bottom >= self.tableView.contentSize.height - self.tableView.bounds.size.height). Also, this works for all subclasses of UIScrollView (UICollectionView and UITableView).Finagle
This will NOT work with storyboard and size classes. Check my answer here.Armada
A
0

In todays times (Xcode 7), below code should solve most use cases since it accounts for UIScrollView (and it's subclasses UITableView and UICollectionView) insets, single storyboard for multiple devices (i.e. size classes) -

func scrollViewDidScroll(scrollView: UIScrollView) {
    if (Int(scrollView.contentOffset.y + scrollView.frame.size.height) == Int(scrollView.contentSize.height + scrollView.contentInset.bottom)) {
        if !isFetching {
            isFetching = true
            fetchAndReloadData(true)
        }
    }
}

PS: Notice Int() and == is important to trigger event once.

Armada answered 18/10, 2015 at 21:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.