使用场景:CABasicAnimation做平移时防止闪回
思路:
之所以要闪回主要是因为动画完成后,屏幕刷新会回到View
的实际位置。CABasicAnimation
做平移的时候没有改变View
实际位置。那就需要自己给View
坐标赋值。
解决办法:
- (void)animationTranslation:(UIView *)animaView duration:(CGFloat)duration tx:(CGFloat)tx ty:(CGFloat)ty finish:(void (^ __nullable)(void))finish{
CABasicAnimation *anima = [CABasicAnimation animationWithKeyPath:@"transform.translation"];
anima.duration = duration;
anima.delegate = self;
//记录上次的值,确保再次运行时不会重复
self.currentOffsetPoint = CGPointMake(tx - self.startOffsetPoint.x, ty - self.startOffsetPoint.y);
self.animaView = animaView;
if (self.startOffsetPoint.x != tx) {
self.startOffsetPoint = CGPointMake(tx,ty);
}
anima.toValue = [NSValue valueWithCGPoint:self.currentOffsetPoint];
[self.animaView.layer addAnimation:anima forKey:@"translation"];
if (finish) {
self.finsh = finish;
}
}
注意:startOffsetPoint
记录的是上一次的偏移量,因为我使用的keyPath
是transform.translation
,只需要知道距离初始位置的偏移就可以了。这里写的作用仅仅是为了避免多次运行,重复动画。
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
CGPoint tempPoint = self.animaView.frame.origin;
CGSize tempSize = self.animaView.frame.size;
[self.animaView.layer removeAnimationForKey:@"translation"];
//给view重新赋值坐标
self.animaView.frame = CGRectMake(tempPoint.x + self.currentOffsetPoint.x, tempPoint.y + self.currentOffsetPoint.y, tempSize.width, tempSize.height);
if (self.finsh) {
self.finsh();
}
}
在代理结束时给View
重新赋值坐标。
闪回原因:
动画作用的是表现层
,而View
的真实属性取自模型层
。每次动画结束,只要没有动画保持在View
上,屏幕刷新就会回到模型层
状态。详细分析可以参考这位仁兄
iOS10代理适配:
因为iOS10
以前,CAAnimationDelegate
被写成了NSObject
的分类,不需要遵守CAAnimationDelegate
协议。但是iOS10
又改成协议了。详情参考
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
@interface AnimationManager()<CAAnimationDelegate>
#else
@interface AnimationManager()
#endif