简体   繁体   English

检测到 UIScrollview 底部

[英]Detect UIScrollview bottom reached

I have a UIScrollView with images and when the user scrolls to the end of the scrollview i want to update the content.我有一个带有图像的 UIScrollView,当用户滚动到滚动视图的末尾时,我想更新内容。 This is my code to detect when the bottom of the scrollview is reached:这是我检测何时到达滚动视图底部的代码:

The code below is implemented in scrollViewDidScroll: delegate下面的代码在scrollViewDidScroll: delegate 中实现

CGFloat scrollViewHeight = imagesScrollView.bounds.size.height;
CGFloat scrollContentSizeHeight = imagesScrollView.contentSize.height;
CGFloat bottomInset = imagesScrollView.contentInset.bottom;
CGFloat scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight;

if(imagesScrollView.contentOffset.y > scrollViewBottomOffset){


    [imagesView addSubview:imagesBottomLoadingView];

    [self downloadImages];

}

My problem is that when the user scrolls to bottom, my function is called several times, but i want to call it only once.我的问题是,当用户滚动到底部时,我的函数被调用了几次,但我只想调用它一次。 I tried with imagesScrollView.contentOffset.y == scrollViewBottomOffset but it doesn't work and the function is not called我尝试使用 imagesScrollView.contentOffset.y == scrollViewBottomOffset 但它不起作用并且未调用该函数

If you want to detect them 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
}}

Carlos answer is better.卡洛斯的回答更好。

For Swift 4.x you must change method name:对于 Swift 4.x,您必须更改方法名称:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if (scrollView.contentOffset.y + 1) >= (scrollView.contentSize.height - scrollView.frame.size.height) {
            //bottom reached
        }
    }
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{
    float bottomEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
    if (bottomEdge >= scrollView.contentSize.height) 
    {
        // we are at the end
    }
}

Have you thought of adding a boolean.你有没有想过添加一个布尔值。 update it when the method is called for the first time and maybe when user scrolls back up.在第一次调用该方法时更新它,也许当用户向上滚动时更新它。

Sometimes you will have to use +1 in the condition because the contentSize.height gives you a few decimals over, so if you use this, you avoid it...有时您将不得不在条件中使用 +1,因为 contentSize.height 给了您几个小数,所以如果您使用它,您可以避免它......

override func scrollViewDidScroll(scrollView: UIScrollView) {

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

实现scrollViewDidScroll:并检查contentOffset以达到终点

For Swift 4.5:对于 Swift 4.5:

func scrollViewDidScroll(_ scrollView: UIScrollView) 
{    
   let scrollViewHeight = scrollView.frame.size.height
    let scrollContentSizeHeight = scrollView.contentSize.height
     let scrollOffset = scrollView.contentOffset.y

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

I used a mixed approach for this.我为此使用了混合方法。 Let me explain:让我解释:

While your calculus is correct, the delegate your listening to is an overkill since scrollViewDidScroll is called many times which can lead to performance issues.虽然您的微积分是正确的,但您收听的委托是一种矫枉过正,因为scrollViewDidScroll被多次调用,这可能会导致性能问题。 You should (as I did) use scrollViewDidEndDragging and scrollViewDidEndDecelerating which are called only once at the end of each of their respective events.您应该(像我一样)使用scrollViewDidEndDraggingscrollViewDidEndDecelerating ,它们仅在每个事件结束时调用一次。

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    // Scrolling acceleration didn't continue after the finger was lifted
    if !decelerate {
        executeActionAtTheEnd(of: scrollView)
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    executeActionAtTheEnd(of: scrollView)
}

private func executeActionAtTheEnd(of scrollView: UIScrollView) {
    if scrollView.contentOffset.y + 1 >= (scrollView.contentSize.height - scrollView.frame.size.height) {
        // Do here whatever you want when end of scrolling is reached
    }
}
func scrollViewDidEndDecelerating(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
}}

Make sure your view implementing the UIScrollViewDelegate确保您的视图实现了 UIScrollViewDelegate

MyView: UITableViewDelegate,UIScrollViewDelegate

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM