修改 view 的非 root layer 的属性时会有默认动画效果(0.25秒)。
@interface CircleAction : NSObject<CAAction>
@property (nonatomic) CGFloat oldProgress;
@end
@implementation CircleAction
-(void)runActionForKey:(NSString *)event object:(id)anObject arguments:(NSDictionary *)dict
{
CircleLayer *cLayer = (CircleLayer*)anObject;
NSLog(@"--- B %.2f",cLayer.progress);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 1;
animation.fromValue = @(self.oldProgress);
animation.toValue = @(cLayer.progress);
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[cLayer addAnimation:animation forKey:@"strokeEnd"];
}
@end
@interface CircleLayer()<CALayerDelegate>
@end
@implementation CircleLayer
@dynamic progress;
- (instancetype)init
{
self = [super init];
if (self) {
self.delegate = self;
}
return self;
}
-(void)setFrame:(CGRect)frame
{
[super setFrame:frame];
UIBezierPath *path = [UIBezierPath bezierPath];
[path addArcWithCenter:CGPointMake(frame.size.width/2.0, frame.size.height/2.0) radius:50 startAngle:0 endAngle:M_PI*2 clockwise:NO];
self.path = path.CGPath;
self.fillColor = [UIColor clearColor].CGColor;
self.strokeColor = [UIColor orangeColor].CGColor;
self.lineWidth = 3;
self.strokeStart = 0;
self.strokeEnd = 1;
}
/*
1、当 CALayer 属性发生改变时候,会调用 - (id<CAAction>)actionForKey:(NSString *)event
2、如果 actionForKey:返回了一个 Action,不会再调用 actionForLayer:forKey:
3、如果 actionForKey:没有返回了一个 Action,则会调用代理的 actionForLayer:forKey:
4、actionForLayer:forKey: 返回的 id 需要实现 runActionForKey: object: arguments:。
*/
-(id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
CircleLayer *cLayer = (CircleLayer*)layer;
NSLog(@"--- A %.2f",cLayer.progress);
CircleAction *action = [[CircleAction alloc] init];
action.oldProgress = cLayer.progress;
return action;
}
@end
@implementation ViewController
{
CircleLayer *_cLayer;
}
- (void)viewDidLoad {
[super viewDidLoad];
_cLayer = [[CircleLayer alloc] init];
_cLayer.frame = CGRectMake(100, 100, 120, 120);
_cLayer.backgroundColor = [UIColor yellowColor].CGColor;
[self.view.layer addSublayer:_cLayer];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
_cLayer.progress = 0.5;
}
@end
参考文章: