I would like to implement "pull down to refresh" type effect on a UIScrollview. On detecting "top" bounce of the scrollview, the view should refresh some of the components. How can I detect the "top bounce" of UIScrollview? I tried the delegate "scrollViewWillBeginDragging" but did not work.
Implement scrollViewDidScroll:, and check the value of scrollView.contentOffset.y -- it will be negative when you pull down, and go back to 0 (or near 0) when it bounces back. Depending on what condition you want to meet to do the refresh, you could set a flag when that value goes to a specific negative value, and then do the refresh when it goes back to near 0. Something like this:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y < -50) _metNegativePullDown = YES;
if (fabs(scrollView.contentOffset.y) < 1 && _metNegativePullDown) {
//do your refresh here
_metNegativePullDown = NO;
}
}
For the record, i'm detecting both bounces on Swift 4 using this category:
extension UIScrollView {
var isBouncing: Bool {
var isBouncing = false
if contentOffset.y >= (contentSize.height - bounds.size.height) {
// Bottom bounce
isBouncing = true
} else if contentOffset.y < contentInset.top {
// Top bounce
isBouncing = true
}
return isBouncing
}
}
Things to consider
- In this case i'm just checking top content inset, if you are going to use bottom inset some tweaking must be necessary
- If your scroll view is direct child of viewcontroller's view and has top constraint to superview instead of top safe area margin this will not do the trick perfect, more tweaking will be necessary
Most answers incorrectly handle the case when you scroll down. The main thing here is to use adjustedContentInset.bottom
which includes both safeAreaInset
and contentInset
. Then it works correctly on iPhones with and without a notch.
extension UIScrollView {
var isBottomBouncing: Bool {
contentOffset.y > max(0.0, contentSize.height - bounds.height + adjustedContentInset.bottom)
}
}
It is a very precise calculation, so if you rely on it in scrollViewDidScroll
you may also need to apply some threshold, because scrollViewDidScroll
may not catch the moment when isBottomBouncing
changes to false
.
© 2022 - 2024 — McMap. All rights reserved.