[英]UIView with custom drawRect and animateWithDuration
I have a UIView
subclass that displays circular progress: 我有一个显示循环进度的
UIView
子类:
Screenshot above shows progress with value of 0.667
. 上面的屏幕截图显示了值为
0.667
进度。
Inside my UIView
subclass implementation in drawRect:
method I am drawing two circles - one for background oval (gray), second for actual progress oval (blue). 在
drawRect:
方法中我的UIView
子类实现内部我绘制了两个圆 - 一个用于背景椭圆(灰色),第二个用于实际进度椭圆(蓝色)。 (Check out source code) (查看源代码)
It works like expected, but doesn't allow to animate progress changes. 它的工作方式与预期相同,但不允许对进度更改进行动画处理。 I tried to find solution that allows using
UIView
's animateWithDuration:animations:
class method like this: 我试图找到允许使用
UIView
的animateWithDuration:animations:
解决方案animateWithDuration:animations:
类方法:
MyCustomView *progressView = ...
[UIView animateWithDuration:3
animations:^{
progressView.progressValue = 1.f;
}];
But I wasn't able to make it animates that way. 但我无法以这种方式制作动画。
You can check out the source code in my GitHub repository . 您可以在我的GitHub存储库中查看源代码。
However, I found a way to perform an animation whenever progressValue
changes. 但是,我发现了一种在
progressValue
发生变化时执行动画的方法。 It's not exactly what I want (still not working with UIView
's animateWithDuration:animations:
), and I am not sure if this is the right direction. 这不是我想要的(仍然没有使用
UIView
的animateWithDuration:animations:
,我不确定这是否是正确的方向。 It involves subclassing CALayer
of my UIView
. 它涉及子类化我的
UIView
CALayer
。 You can check out the source code in the same repo mentioned above, on custom_layer branch . 您可以在custom_layer分支上查看上面提到的同一个repo中的源代码。 Here is direct link to
CALayer
subclass drawing implementation. 这是
CALayer
子类绘图实现的直接链接 。
My question is: Having a UIView
subclass that draws some shapes based on custom properties ( progressValue
), is it possible to make the view animates with UIView
's animateWithDuration:animations:
when changing the view's property ( progressValue
) ? 我的问题是:有一个基于自定义属性(
progressValue
)绘制一些形状的UIView
子类,是否可以使用UIView
的animateWithDuration:animations:
进行视图动画animateWithDuration:animations:
更改视图的属性( progressValue
)?
UPDATE UPDATE
Thanks to rounak's answer I get rid of drawing custom shapes in drawRect:
method and created two separate CAShapeLayer
s. 感谢rounak的回答,我摆脱了
drawRect:
方法中绘制自定义形状并创建了两个单独的CAShapeLayer
。 Instead of drawing new shapes every time progressValue
changes, I am just setting strokeEnd
properties for that layers, which gives the same visual effect as before, but should perform better ( check out source code ). 我不是每次
progressValue
更改时都绘制新的形状,而只是为这些图层设置strokeEnd
属性,它们提供与以前相同的视觉效果,但应该表现更好( 查看源代码 )。
Then I implemented actionForLayer:forKey:
method ( check out source code ), which returns CABasicAnimation
that should animate strokeEnd
whenever progressValue
changes. 然后我实现了
actionForLayer:forKey:
方法( 检查源代码 ),它返回CABasicAnimation
,它应该在progressValue
改变时为strokeEnd
设置动画。
However, I am still experiencing an issue with the animation: 但是,我仍然遇到动画问题:
__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];
}];
}];
My circular progress view animates progressValue
changes, and executing the code above tells that each animation takes about 3 seconds. 我的循环进度视图为
progressValue
更改设置动画,并执行上面的代码告诉每个动画大约需要3秒钟。 Unfortunately, on screen the view animates very fast (animation completes in fraction of a second). 不幸的是,在屏幕上,视图动画非常快(动画在几分之一秒内完成)。 Here is what it looks like:
这是它的样子:
I am not sure where the problem is, but I noticed that changing keypath in [CABasicAnimation animationWithKeyPath:@"strokeEnd"]
from strokeEnd
to anything else doesn't gives any effect (animation always looks the same). 我不确定问题出在哪里,但我注意到将
[CABasicAnimation animationWithKeyPath:@"strokeEnd"]
的strokeEnd
从strokeEnd
为其他任何内容都不会产生任何效果(动画总是看起来一样)。
Any hints of what I am missing here will be appreciated. 任何我在这里缺少的提示将不胜感激。
UPDATE 2 更新2
I have just noticed that animation is in fact triggered by those two lines in setProgressValue:
setter: 我刚刚注意到动画实际上是由
setProgressValue:
这两行触发的setProgressValue:
setter:
self.progressOvalLayer.strokeEnd = MIN(1, MAX(0, progressValue));
self.backgroundOvalLayer.strokeEnd = MIN(1, MAX(0, 1 - progressValue));
( see on GitHub ) ( 参见GitHub )
It looks like my implementation of actionForLayer:forKey:
does not work at all, despite being executed (checked with brakepoint). 看起来我的
actionForLayer:forKey:
实现actionForLayer:forKey:
尽管被执行了,但根本不起作用(用brakepoint检查)。
I wonder what I am doing wrong? 我想知道我做错了什么?
UPDATE - SOLUTION FOUND 更新 - 解决方案
It occurred that I tried to animate main layer of my UIView
instead of custom layers that contains oval shapes. 我试图为我的
UIView
主图层设置动画,而不是包含椭圆形状的自定义图层。 I needed to fix actionForLayer:(CALayer *)layer forKey:
implementation to make it works ( check out fixed source code ). 我需要修复
actionForLayer:(CALayer *)layer forKey:
实现使其工作( 检查固定的源代码 )。 That solves my problem. 这解决了我的问题。
I'd suggest you draw the circular progress with a CAShapeLayer
, and use the strokeStart
, strokeEnd
, and fillColor
properties to achieve your effect. 我建议你画一个圆形进度
CAShapeLayer
,并使用strokeStart
, strokeEnd
,并fillColor
属性来实现你的效果。 You'll likely need two shapeLayers, one over the other, but the advantage with this approach is that shapeLayer's properties are animateable via CoreAnimation. 您可能需要两个shapeLayers,一个在另一个之上,但这种方法的优点是shapeLayer的属性可以通过CoreAnimation进行动画处理。
Additionally, you can use hackery like this to make it animate within animation blocks as well https://gist.github.com/nicklockwood/d374033b27c62662ac8d 此外,您可以使用这样的hackery在动画块中制作动画,以及https://gist.github.com/nicklockwood/d374033b27c62662ac8d
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.