题 检测UIScrollView是否正在滚动


我想要检测是否(不是何时)a UIScrollView 在滚动。

BOOL isScrolling = myscrollview.scrolling;

我将如何实现这一目标? .dragging 和 .decelerating 不适用的时候 setContentOffset:animated: 用来。


13
2017-12-10 07:59


起源


怎么样 scrollViewDidScroll 委托方法? - iDev
那只回答“什么时候”。 - Jonny
有点复杂,但根据您想要此信息的原因,您可以查看主运行循环的模式。例如,当前没有滚动视图滚动或被拖动,您的主要运行循环可能会在 NSDefaultRunLoopMode。如果任何滚动视图正在滚动/被拖动,它将处于不同的模式,部分 NSRunLoopCommonModes。例如,如果您想等待滚动结束以执行某些操作,则可以使用 CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, block); - Guillaume
嗯,好的,谢谢,但我不会去那里......我想所吸取的教训是避免使用“.scrolling”方法。因为某些原因 setContentOffset:animated: 动画设置为NO会调用 scrollViewDidScroll 但不是 scrollViewDidEndScrollingAnimation:......这不公平...... - Jonny
@Jonny:你的解决方案是什么? - testing


答案:


这可能是一种略微狡猾的方式,但我之前在我的代码中使用过它并没有让我失望。 :)

#import <QuartzCore/QuartzCore.h>
---
BOOL isScrolling = [scrollView.layer animationForKey:@"bounds"] != nil;

除了'self.contentOffset'之外,UIScrollView的偏移量也存储在UIView的“bounds.origin”属性中(我想因为它在低级代码中更方便一些)。当你调用[setContentOffset:animated:]时,它将它作为CABasicAnimation传递给UIScrollView,操纵“bounds”属性。

当然,如果scrollView本身的形状是动画,则此检查也将返回true。在这种情况下,您可能需要实际将边界对象拉出动画([CAAnimation toValue])并进行手动比较以查看“origin”本身是否正在发生变化。

这不是最优雅的解决方案,但我希望能够避免在任何可能的情况下使用代理。特别是如果有问题的类是UIScrollView子类。 :)


15
2018-03-25 16:29



感谢TiM的回答,你知道它是否通过了Apple的审核流程吗? - Randy
不用担心兰迪!是的!确实如此。它没有触及任何私有API。我已经在App Store中使用这行代码开了两年多的应用程序。 :) - TiM


我通常通过在中设置一个布尔变量来做到这一点 scrollViewWillBeginDragging: 和 scrollViewDidEndDragging:willDecelerate: 事件。

UIScrollView文档


6
2017-12-10 08:03



我没有使用拖动...即使我猜我仍然不会捕获setContentOffset:animated - Jonny
你也可以实现 scrollViewDidEndScrollingAnimation: 这将在动画发布时调用 setContentOffset:animated: 结束... - Guillaume
@Guillaume:我测试了它,如果你使用动画它会起作用。您是否使用与您同时设置的属性 setContentOffset?还是有另一种可能性来检查滚动何时开始?是否有可能不使用动画? - testing


不是一个非常干净的解决方案..但应该是最可靠的:

var isScrolling = false

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    isScrolling = true
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate { scrollViewDidEndScrolling(scrollView) }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    scrollViewDidEndScrolling(scrollView)
}

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
    scrollViewDidEndScrolling(scrollView)
}

func scrollViewDidEndScrolling(_ scrollView: UIScrollView) {
    isScrolling = false
}

3
2018-05-22 13:16





- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;

使用标志来保存当前滚动状态? 它只能解决setContentOffset:animated:problem。

“滚动”只是一种效果,有许多方法使滚动视图“滚动”,例如,连续设置内容偏移量。所以这个问题应该没有答案。


0
2018-01-22 03:59