回答你的第一个问题
每个运行循环只会调用一次layoutSubviews。您可以根据需要多次调用 [self setNeedsLayout],而不必担心不必要地布局视图会影响性能。
参考自:
库比切克、吉姆. “滥用 UIView。” 2012 年 10 月 11 日。http://jimkubicek.com/blog/2012/10/11/using-uiview/
要回答你的第二个问题,你对它闪烁的原因是正确的。问题在于,无法保证在重置图层外观之前调用animationDidStop回调方法。
有几种方法可以解决此问题,以下方法仅涉及添加一些额外的代码,而无需更改现有代码。
//kCAFillModeForwards: the animatable properties take on the end value once it has finished
[strokeAnimation setFillMode:kCAFillModeForwards];
[strokeAnimation setRemovedOnCompletion:NO];
[fillAnimation setFillMode:kCAFillModeForwards];
[fillAnimation setRemovedOnCompletion:NO];
[group setFillMode:kCAFillModeForwards];
[group setRemovedOnCompletion:NO];
[self.checkmarkLayer addAnimation:group forKey:nil];
当 CAAnimation 完成时,它会将自身从图层中删除并导致图层重置,因此我们要做的第一件事就是阻止动画被删除。
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
if (theBlock)
theBlock();
[self.checkmarkLayer removeAllAnimations];
}
当调用animationDidStop方法时,我们像以前一样设置图层的属性,然后从图层中删除动画。
另一件需要考虑的事情是,当您更改 CALayer 的外观时,它会隐式(自动)动画化。因此,当您设置完成块时,您需要明确告诉核心动画不要设置动画
animationCompletionBlock block;
block = ^(void){
[CATransaction begin];
[CATransaction setDisableActions:YES];
[self.checkmarkLayer setFillColor:[UIColor whiteColor].CGColor];
[CATransaction commit];
};