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