我有一个显示循环进度的UIView子类:
上面的屏幕截图显示了值为0.667的进度.
在drawRect:方法中我的UIView子类实现内部我绘制了两个圆 – 一个用于背景椭圆(灰色),第二个用于实际进度椭圆(蓝色). (Check out source code)
它的工作方式与预期相同,但不允许对进度更改进行动画处理.我试图找到允许使用UIView的animateWithDuration的解决方案:动画:这样的类方法:
MyCustomView *progressView = ...
[UIView animateWithDuration:3
animations:^{
progressView.progressValue = 1.f;
}];
但我无法以这种方式制作动画.
您可以在my GitHub repository查看源代码.
但是,我发现了一种在progressValue发生变化时执行动画的方法.这不是我想要的(仍然没有使用UIView的animateWithDuration:动画:),我不确定这是否是正确的方向.它涉及子类化我的UIView的CALayer.您可以在上面提到的同一个repo中查看源代码,on custom_layer branch.这是direct link到CALayer子类的绘图实现.
我的问题是:拥有一个基于自定义属性(progressValue)绘制一些形状的UIView子类,是否可以使用UIView的animateWithDuration来制作视图动画:动画:更改视图的属性(progressValue)时?
UPDATE
感谢rounak’s answer,我摆脱了drawRect:方法中的自定义形状,并创建了两个单独的CAShapeLayers.每次progressValue更改时,我只是为这些图层设置strokeEnd属性而不是绘制新形状,而是提供与之前相同的视觉效果,但应该表现更好(check out source code).
然后我实现了actionForLayer:forKey:方法(check out source code),它返回CABasicAnimation,它应该在progressValue改变时为strokeEnd设置动画.
但是,我仍然遇到动画问题:
__block NSDate *date = [NSDate date];
[UIView animateWithDuration:3
animations:^{
self.progressView.progressValue = 1.f;
}
completion:^(BOOL finished1) {
NSLog(@"first animation completed in %f", [[NSDate date] timeIntervalSinceDate:date]);
date = [NSDate date];
[UIView animateWithDuration:3
animations:^{
self.progressView.progressValue = 0.f;
}
completion:^(BOOL finished2) {
NSLog(@"second animation completed in %f", [[NSDate date] timeIntervalSinceDate:date]);
[self animateProgress];
}];
}];
我的循环进度视图为progressValue更改设置动画,并执行上面的代码告诉每个动画大约需要3秒钟.不幸的是,在屏幕上,视图动画非常快(动画在几分之一秒内完成).这是它的样子:
我不确定问题出在哪里,但我注意到将[CABasicAnimation animationWithKeyPath:@“strokeEnd”]中的keypath从strokeEnd更改为其他任何内容都不会产生任何效果(动画总是看起来一样).
任何我在这里缺少的提示将不胜感激.
更新2
我刚刚注意到动画实际上是由setProgressValue中的这两行触发的:setter:
self.progressOvalLayer.strokeEnd = MIN(1, MAX(0, progressValue));
self.backgroundOvalLayer.strokeEnd = MIN(1, MAX(0, 1 - progressValue));
看起来我的actionForLayer的实现:forKey:尽管被执行了,但根本不起作用(用brakepoint检查).
我想知道我做错了什么?
更新 – 解决方案
我试图为我的UIView的主图层设置动画,而不是包含椭圆形状的自定义图层.我需要修复actionForLayer:(CALayer *)图层forKey:实现使它工作(check out fixed source code).这解决了我的问题.
最佳答案 我建议您使用CAShapeLayer绘制循环进度,并使用strokeStart,strokeEnd和fillColor属性来实现您的效果.您可能需要两个shapeLayers,一个在另一个之上,但这种方法的优点是shapeLayer的属性可以通过CoreAnimation进行动画处理.
此外,你可以使用像这样的hackery来使动画块中的动画像https://gist.github.com/nicklockwood/d374033b27c62662ac8d一样