UIScrollViewDelegate scrollViewDidScroll 方法跟不上高速滚动(轻弹)?

Posted

技术标签:

【中文标题】UIScrollViewDelegate scrollViewDidScroll 方法跟不上高速滚动(轻弹)?【英文标题】:UIScrollViewDelegate scrollViewDidScroll method not keeping up with high-velocity scrolling (flick)? 【发布时间】:2017-09-28 16:53:32 【问题描述】:

我有一个UIScrollView 和一个UIView 标头,它贴在滚动视图的顶部,并在用户向下滚动时从全尺寸缩小到小尺寸。当然,这些是通过滚动视图委托实现的:

// scroll view delegate
extension SomeViewController 

    // scroll view did scroll
    public func scrollViewDidScroll(_ scrollView: UIScrollView) 

        let contentOffsetY = scrollView.contentOffset.y

        // make banner sticky
        banner.frame.origin.y = max(0, contentOffsetY)

        // shrink banner
        if contentOffsetY > 0 && contentOffsetY <= bannerHeight! - 64 
            banner.frame.size.height = bannerHeight! - contentOffsetY
            bannerGraphic.frame = banner.bounds
        

    


效果很好...如果用户不高速滚动。如果用户轻弹以向下滚动(高速),代表似乎跟不上,并且横幅永远不会完全缩小(可能是 85-90%)。为了验证这一点,我将滚动视图的偏移量打印到控制台,并注意到当用户缓慢滚动时,控制台可能会打印 100 行当前偏移量。并且当用户快速滚动时,控制台可能会打印 25 行当前偏移量。代表根本无法跟上高速滚动。

有没有办法确保横幅在不考虑滚动速度的情况下缩小,或者这只是 UIKit 的方式?

【问题讨论】:

您希望banner.frame.size.height至少 64 岁吗?还是应该缩小到零? 至少 64 个(状态栏 + 导航栏) 好的-并且...如果您在滚动视图内容一直位于顶部的情况下向下拉,那么.contentOffset.y &lt; 0,横幅是否应该从顶部向下移动?还是保持“固定”在顶部,并保持其原始大小? 横幅在下拉时不应保持固定 好的 - 看看我的回答。 【参考方案1】:

ScrollView 委托不会收到关于视图滚动的每一个点的通知。而且你真的不希望这样......这将是太多不必要的处理。

因此,在快速滚动时完全有可能出现较大的间隙。事实上,在一个快速测试中,我只是将.contentOffsetY 的值从 0 跳到 75 到 300...

您的代码很接近。你想要做的是在你超过你的最大值时处理这个条件。

试一试(我认为它只会插入并替换您的功能):

extension TestViewController: UIScrollViewDelegate 

    // scroll view did scroll
    public func scrollViewDidScroll(_ scrollView: UIScrollView) 

        let contentOffsetY = scrollView.contentOffset.y

        // make banner sticky
        banner.frame.origin.y = max(0, contentOffsetY)

        // if scrollView content is all the way at the top 
        // (or pulled down, waiting to "bounce back up")

        if contentOffsetY <= 0 

            // set banner to original height
            banner.frame.size.height = bannerHeight
            bannerGraphic.frame = banner.bounds

         else 

            // view has scrolled (user has dragged *up*)

            // set banner height to originalHeight - y offset,
            // but keep it a minimum of 64

            banner.frame.size.height = max(bannerHeight! - contentOffsetY, 64)
            bannerGraphic.frame = banner.bounds

        

    


【讨论】:

很高兴为您提供帮助:)

以上是关于UIScrollViewDelegate scrollViewDidScroll 方法跟不上高速滚动(轻弹)?的主要内容,如果未能解决你的问题,请参考以下文章

在 UICollectionView 子类中实现 UIScrollViewDelegate

成为 UITableView 的 UIScrollViewDelegate 代表

从 UITableView 的子类访问 UIScrollViewDelegate

在 UICollectionView 中滚动时绕过 UIScrollViewDelegate

为啥我的 UIScrollViewDelegate 没有在快速操场上被调用?

未调用 UIScrollViewDelegate 函数