[英]UIView with custom drawRect and animateWithDuration
我有一个显示循环进度的UIView
子类:
上面的屏幕截图显示了值为0.667
进度。
在drawRect:
方法中我的UIView
子类实现内部我绘制了两个圆 - 一个用于背景椭圆(灰色),第二个用于实际进度椭圆(蓝色)。 (查看源代码)
它的工作方式与预期相同,但不允许对进度更改进行动画处理。 我试图找到允许使用UIView
的animateWithDuration:animations:
解决方案animateWithDuration:animations:
类方法:
MyCustomView *progressView = ...
[UIView animateWithDuration:3
animations:^{
progressView.progressValue = 1.f;
}];
但我无法以这种方式制作动画。
您可以在我的GitHub存储库中查看源代码。
但是,我发现了一种在progressValue
发生变化时执行动画的方法。 这不是我想要的(仍然没有使用UIView
的animateWithDuration:animations:
,我不确定这是否是正确的方向。 它涉及子类化我的UIView
CALayer
。 您可以在custom_layer分支上查看上面提到的同一个repo中的源代码。 这是CALayer
子类绘图实现的直接链接 。
我的问题是:有一个基于自定义属性( progressValue
)绘制一些形状的UIView
子类,是否可以使用UIView
的animateWithDuration:animations:
进行视图动画animateWithDuration:animations:
更改视图的属性( progressValue
)?
UPDATE
感谢rounak的回答,我摆脱了drawRect:
方法中绘制自定义形状并创建了两个单独的CAShapeLayer
。 我不是每次progressValue
更改时都绘制新的形状,而只是为这些图层设置strokeEnd
属性,它们提供与以前相同的视觉效果,但应该表现更好( 查看源代码 )。
然后我实现了actionForLayer:forKey:
方法( 检查源代码 ),它返回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"]
的strokeEnd
从strokeEnd
为其他任何内容都不会产生任何效果(动画总是看起来一样)。
任何我在这里缺少的提示将不胜感激。
更新2
我刚刚注意到动画实际上是由setProgressValue:
这两行触发的setProgressValue:
setter:
self.progressOvalLayer.strokeEnd = MIN(1, MAX(0, progressValue));
self.backgroundOvalLayer.strokeEnd = MIN(1, MAX(0, 1 - progressValue));
( 参见GitHub )
看起来我的actionForLayer:forKey:
实现actionForLayer:forKey:
尽管被执行了,但根本不起作用(用brakepoint检查)。
我想知道我做错了什么?
更新 - 解决方案
我试图为我的UIView
主图层设置动画,而不是包含椭圆形状的自定义图层。 我需要修复actionForLayer:(CALayer *)layer forKey:
实现使其工作( 检查固定的源代码 )。 这解决了我的问题。
我建议你画一个圆形进度CAShapeLayer
,并使用strokeStart
, strokeEnd
,并fillColor
属性来实现你的效果。 您可能需要两个shapeLayers,一个在另一个之上,但这种方法的优点是shapeLayer的属性可以通过CoreAnimation进行动画处理。
此外,您可以使用这样的hackery在动画块中制作动画,以及https://gist.github.com/nicklockwood/d374033b27c62662ac8d
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.