You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:25:14