【问题标题】:Check if a UIScrollView reached the top or bottom检查 UIScrollView 是否到达顶部或底部
【发布时间】:2011-12-04 02:29:43
【问题描述】:

有没有办法知道UIScrollView 是到达顶部还是底部?可能在方法中:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView 
                  willDecelerate:(BOOL)decelerate

【问题讨论】:

    标签: ios objective-c iphone uiscrollview uiscrollviewdelegate


    【解决方案1】:

    在你的类中实现UIScrollViewDelegate,然后添加:

    -(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
        }
    }
    

    希望这就是你所追求的!否则,通过在上面的代码中添加更多条件和 NSLog 滚动偏移的值来进行修改。

    【讨论】:

    • 如果您在 navigationController 中,您可能想做更多类似的事情:scrollOffset <= (0 - self.navigationController.navigationBar.frame.size.height - 20)(scrollOffset + scrollHeight) >= scrollContentSizeHeight
    • 反弹的问题...一旦到达顶部或底部,所有东西都会被调用两次。除了关闭表格或集合视图反弹之外,还有其他解决方案吗?
    • @denikov 你找到解决方案了吗?
    • scrollOffset 可能是
    【解决方案2】:

    好吧,contentInsets 也参与其中,当您尝试确定 scrollView 是在顶部还是在底部时。当您的 scrollView 位于 above 顶部和 below 底部时,您可能还会感兴趣。 这是我用来查找顶部和底部位置的代码:

    斯威夫特:

    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
        }
    
    }
    

    目标-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
    

    【讨论】:

    • 这是个好答案,实现 scrollviewdidscroll 对性能不利
    • 不使用scrollViewDidScroll怎么调用?
    • 由于浮点数学的变幻莫测,我得到了 1879.05xxx 的“verticalOffsetForBottom”,而我的 contentOffset.y 在 Swift 3 中处于底部时为 1879。所以我将 return scrollViewBottomOffset 更改为 @ 987654325@
    • 从 iOS 11 开始 safeAreaInsets 也考虑在内。 scrollView.contentOffset.y + scrollView.bounds.height - scrollView.safeAreaInsets.bottom
    • 在 iOS 11 及更高版本中,您可能需要使用adjustedContentInset 而不是contentInset
    【解决方案3】:

    如果你想要 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
        }
    }
    

    【讨论】:

      【解决方案4】:

      简单干净的扩展:

      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
          }
      
      }
      

      在 GitHub 上:

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

      【讨论】:

        【解决方案5】:

        我知道该怎么做:

        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!
        }
        

        【讨论】:

          【解决方案6】:

          这样做(对于 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
                  }
          
          
              }
          }
          

          【讨论】:

          • 欢迎来到 SO!在您的答案中发布代码时,有助于解释您的代码如何解决 OP 的问题 :)
          猜你喜欢
          • 2017-11-19
          • 1970-01-01
          • 1970-01-01
          • 2020-02-01
          • 2015-11-11
          • 1970-01-01
          • 2016-10-28
          • 2014-09-17
          • 1970-01-01
          相关资源
          最近更新 更多