检查 UIScrollView 是否到达顶部或底部

是否有办法知道 UIScrollView是否已经到达顶部或底部? 可能的方法是:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate
64301 次浏览

Implement the UIScrollViewDelegate in your class, and then add this:

-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
float scrollViewHeight = scrollView.frame.size.height;
float scrollContentSizeHeight = scrollView.contentSize.height;
float scrollOffset = scrollView.contentOffset.y;


if (scrollOffset == 0)
{
// then we are at the top
}
else if (scrollOffset + scrollViewHeight == scrollContentSizeHeight)
{
// then we are at the end
}
}

Hope this is what you are after! Else have a tinker by adding more conditions to the above code and NSLog the value of scrollOffset.

Well, contentInsets are also involved, when you try to determine whether scrollView is at the top or at the bottom. You might also be interested in cases when your scrollView is above the top and below the bottom. Here is the code I use to find top and bottom positions:

Swift:

extension UIScrollView {


var isAtTop: Bool {
return contentOffset.y <= verticalOffsetForTop
}


var isAtBottom: Bool {
return contentOffset.y >= verticalOffsetForBottom
}


var verticalOffsetForTop: CGFloat {
let topInset = contentInset.top
return -topInset
}


var verticalOffsetForBottom: CGFloat {
let scrollViewHeight = bounds.height
let scrollContentSizeHeight = contentSize.height
let bottomInset = contentInset.bottom
let scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight
return scrollViewBottomOffset
}


}

Objective-C:

@implementation UIScrollView (Additions)


- (BOOL)isAtTop {
return (self.contentOffset.y <= [self verticalOffsetForTop]);
}


- (BOOL)isAtBottom {
return (self.contentOffset.y >= [self verticalOffsetForBottom]);
}


- (CGFloat)verticalOffsetForTop {
CGFloat topInset = self.contentInset.top;
return -topInset;
}


- (CGFloat)verticalOffsetForBottom {
CGFloat scrollViewHeight = self.bounds.size.height;
CGFloat scrollContentSizeHeight = self.contentSize.height;
CGFloat bottomInset = self.contentInset.bottom;
CGFloat scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight;
return scrollViewBottomOffset;
}




@end

I figured out exactly how to do it:

CGFloat maxPosition = scrollView.contentInset.top + scrollView.contentSize.height + scrollView.contentInset.bottom - scrollView.bounds.size.height;
CGFloat currentPosition = scrollView.contentOffset.y + self.topLayoutGuide.length;


if (currentPosition == maxPosition) {
// you're at the bottom!
}

If you want the code in swift:

override func scrollViewDidScroll(scrollView: UIScrollView) {


if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
//reach bottom
}


if (scrollView.contentOffset.y <= 0){
//reach top
}


if (scrollView.contentOffset.y > 0 && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)){
//not top and not bottom
}
}

Simple and clean extension:

import UIKit


extension UIScrollView {


var scrolledToTop: Bool {
let topEdge = 0 - contentInset.top
return contentOffset.y <= topEdge
}


var scrolledToBottom: Bool {
let bottomEdge = contentSize.height + contentInset.bottom - bounds.height
return contentOffset.y >= bottomEdge
}


}

On GitHub:

https://github.com/salutis/swift-scroll-view-edges

Do it like this(for Swift 3):

class MyClass: UIScrollViewDelegate {


func scrollViewDidScroll(_ scrollView: UIScrollView) {


if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
//scrolled to top, do smth
}




}
}