如何在Cell复用后恢复CAAnimation Group动画?
解决Cell复用后CAAnimation无法恢复的问题
我之前也踩过一模一样的坑!你说的没错,苹果官方QA1673的暂停/恢复方法只适用于你主动暂停的动画,而Cell滚出屏幕时,系统是主动终止了动画(从animationDidStop:finished:的flag=YES就能明确看出来),这时候已停止的动画根本没法直接恢复,必须换个思路:保存动画进度,复用Cell时重新创建动画并从断点续跑。
下面是我实测有效的方案,分两步走:
1. 在Cell即将被复用时,记录当前动画进度
不管是在Cell的prepareForReuse方法,还是TableView的didEndDisplayingCell代理方法里,我们都可以捕获动画的当前运行进度,然后移除旧动画(避免复用冲突)。
先给你的自定义Cell加个属性用来存进度:
@property (nonatomic, assign) CGFloat animationProgress;
然后在prepareForReuse里记录进度:
- (void)prepareForReuse { [super prepareForReuse]; NSString *animationKey = @"YourUniqueAnimationKey"; // 给你的动画设个唯一Key if ([self.layer animationForKey:animationKey]) { CAAnimation *anim = [self.layer animationForKey:animationKey]; // 计算当前进度:已运行时间 / 动画总时长 CFTimeInterval currentTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil]; CFTimeInterval elapsedTime = currentTime - self.layer.beginTime; self.animationProgress = elapsedTime / anim.duration; // 把进度限制在0~1之间,避免异常值 self.animationProgress = MAX(0.0, MIN(1.0, self.animationProgress)); // 移除旧动画 [self.layer removeAnimationForKey:animationKey]; } }
2. 复用Cell时,从保存的进度重新启动动画
在你给Cell配置数据的方法里(比如configureWithModel:),重新创建动画,并根据之前保存的进度设置起始时间,让动画从断点继续:
- (void)configureWithModel:(YourModel *)model { // 先做你的数据配置逻辑... NSString *animationKey = @"YourUniqueAnimationKey"; [self.layer removeAnimationForKey:animationKey]; // 保险起见,先移除旧动画 // 创建你的CAAnimation(这里以CABasicAnimation为例,换成你自己的动画类型即可) CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; anim.fromValue = @0.8; anim.toValue = @1.2; anim.duration = 1.5; anim.repeatCount = HUGE_VALF; // 无限重复 anim.autoreverses = YES; anim.fillMode = kCAFillModeForwards; anim.removedOnCompletion = NO; // 如果有保存的进度,设置动画的起始时间 if (self.animationProgress > 0) { // 计算需要跳过的时间:总时长 × 已完成进度 CFTimeInterval skipTime = anim.duration * self.animationProgress; // 设置图层的beginTime,让动画从指定进度开始 self.layer.beginTime = CACurrentMediaTime() - skipTime; } else { // 没有进度记录,重置图层时间属性 self.layer.beginTime = 0; } // 添加动画到图层 [self.layer addAnimation:anim forKey:animationKey]; // 重置进度,避免影响下次复用 self.animationProgress = 0.0; }
关键注意点
- 一定要给动画设置唯一的Key,这样才能准确获取和移除对应的动画;
- 动画的
removedOnCompletion设为NO,fillMode设为kCAFillModeForwards,确保动画状态能保留; - 不要在Cell的
init或awakeFromNib里添加动画,必须在配置数据的方法里动态创建,这样复用的时候才能灵活控制。
为什么QA1673的方法没用?因为系统终止动画后,动画的finished状态已经被设为YES,此时无论怎么调整图层的speed、timeOffset,都没法让一个已完成的动画重新运行,只能重新创建并续跑。
内容的提问来源于stack exchange,提问作者Huanrong
相关产品推荐
相关产品推荐

