CABasicAnimation 退后台动画暂停

it2025-08-29  3

这回我们来总结一下CABasicAnimation使用中的一些细节的处理问题,避免一些比较蛋疼的事情发生,显得无从下手:

一般的动画,我们这样写: ///开始旋转 - (void)beginRotation { CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; anim.toValue = @(2 * M_PI); anim.duration = 20; anim.repeatCount = MAXFLOAT; [self.iconView.layer addAnimation:anim forKey:nil]; } 确实是能转起来了,但是我们慢慢的把问题引出来,我们先包装一个导航控制器,以及点击item跳转:大概一开始是这么一个效果:  - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.iconView]; [self beginRotation]; }

这个旋转动画的代码,我们放在viewDidLoad里面调,那么一运行程序是会转起来,没错。但是我们点击跳转之后,再回来这个控制器,发现就不转了,这里不绕弯子了,直接是解决办法:

anim.removedOnCompletion = NO;

只要不移除它,等一下跳转回来之后,还能继续旋转。


那么我们看一下回到后台,再进来,还是可以继续旋转的,但是我们会发现有一个跳跃的过程,因为憋太久了,所以给用户的体验,不是那么的完美,我们现在来解决一下:  那么我们就要监听应用退到后台以及前台:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];

进而我们写两个方法来进行操作:

///监听应用退到后台 - (void)didEnterBackground { //记录暂停时间 CFTimeInterval pauseTime = [self.iconView.layer convertTime:CACurrentMediaTime() fromLayer:nil]; //设置动画速度为0 self.iconView.layer.speed = 0; //设置动画的偏移时间 self.iconView.layer.timeOffset = pauseTime; } 前台的操作 ///恢复旋转 - (void)didBecomeActive { //暂停的时间 CFTimeInterval pauseTime = self.iconView.layer.timeOffset; //设置动画速度为1 self.iconView.layer.speed = 1; //重置偏移时间 self.iconView.layer.timeOffset = 0; //重置开始时间 self.iconView.layer.beginTime = 0; //计算开始时间 CFTimeInterval timeSincePause = [self.iconView.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pauseTime; //设置开始时间 self.iconView.layer.beginTime = timeSincePause; }

那么到这里,这个动画基本上也就完成了.


上面的退后台动画暂停很完美, 但是我们的场景不太一样, 我们的动画repeatCount为1, 当用户操作触发第二次动画的时候, 动画展示的效果有异常, 于是我们多做了一步操作. 

回到前台之后 , 继续刚才的暂停动画, 然后等动画结束后(记录动画开始的时间, 动画剩余时间 = duration+timeSincePause-(当前时间-动画开始时间)  ), 把添加动画的view移除掉, 然后重新生成一个动画view, 这样展示效果就正常了.

 

最新回复(0)