如何检测UIScrollView是否已停止动画运动?
UIScrollView 代码触发动画滚动时判断状态的方法
当你通过[self.scrollView setContentOffset:newOffset animated:YES];触发滚动时,isTracking和decelerating确实无法判断滚动状态——因为这两个属性仅针对用户触摸触发的滚动行为,代码驱动的动画滚动不属于这类场景,所以会一直返回NO。下面是几种可行的判断方案:
方案1:利用滚动视图代理的专属回调
UIScrollViewDelegate提供了scrollViewDidEndScrollingAnimation:方法,这个方法会专门在代码触发的滚动动画结束时调用(比如setContentOffset:animated:或scrollRectToVisible:animated:执行完毕)。
你可以结合一个实例变量来跟踪滚动状态:
// 声明实例变量 @property (nonatomic, assign) BOOL isAnimatingProgrammaticScroll; // 触发滚动时标记状态 self.isAnimatingProgrammaticScroll = YES; [self.scrollView setContentOffset:newOffset animated:YES]; // 代理方法中标记结束 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { self.isAnimatingProgrammaticScroll = NO; // 此时滚动已到达最终位置 }
如果需要实时判断,除了检查isAnimatingProgrammaticScroll,还可以对比当前contentOffset与目标newOffset(注意浮点精度问题,建议用极小阈值判断):
CGFloat threshold = 0.5f; BOOL reachedTarget = ABS(scrollView.contentOffset.x - newOffset.x) < threshold && ABS(scrollView.contentOffset.y - newOffset.y) < threshold;
方案2:用UIView动画包装滚动操作
既然代码触发的滚动本质是UIView动画,你可以直接用UIView的动画API来实现,通过completion回调感知动画结束:
CGPoint targetOffset = newOffset; [UIView animateWithDuration:0.3 animations:^{ self.scrollView.contentOffset = targetOffset; } completion:^(BOOL finished) { // 动画完成,滚动到达最终位置 if (finished) { // 处理结束逻辑 } }];
这种方式无需依赖UIScrollViewDelegate,直接通过动画回调即可明确滚动状态。
方案3:实时对比目标偏移量
如果你能持续获取到目标偏移量,也可以在scrollViewDidScroll:中实时判断当前偏移量是否接近最终位置:
// 假设你能拿到目标偏移量targetOffset CGFloat threshold = 1.0f; BOOL isAtFinalPosition = (fabs(scrollView.contentOffset.x - targetOffset.x) < threshold) && (fabs(scrollView.contentOffset.y - targetOffset.y) < threshold);
这种方式适合需要在滚动过程中实时判断是否到达终点的场景。
内容的提问来源于stack exchange,提问作者gerbil
相关产品推荐
相关产品推荐

