繁体   English   中英

UIView使用自定义drawRect和animateWithDuration

[英]UIView with custom drawRect and animateWithDuration

我有一个显示循环进度的UIView子类:

循环进度视图

上面的屏幕截图显示了值为0.667进度。

drawRect:方法中我的UIView子类实现内部我绘制了两个圆 - 一个用于背景椭圆(灰色),第二个用于实际进度椭圆(蓝色)。 (查看源代码)

它的工作方式与预期相同,但不允许对进度更改进行动画处理。 我试图找到允许使用UIViewanimateWithDuration:animations:解决方案animateWithDuration:animations:类方法:

MyCustomView *progressView = ...
[UIView animateWithDuration:3 
                 animations:^{
                     progressView.progressValue = 1.f;
                 }];

但我无法以这种方式制作动画。

您可以在我的GitHub存储库中查看源代码。

但是,我发现了一种在progressValue发生变化时执行动画的方法。 这不是我想要的(仍然没有使用UIViewanimateWithDuration:animations: ,我不确定这是否是正确的方向。 它涉及子类化我的UIView CALayer 您可以在custom_layer分支上查看上面提到的同一个repo中的源代码。 这是CALayer子类绘图实现的直接链接

我的问题是:有一个基于自定义属性( progressValue )绘制一些形状的UIView子类,是否可以使用UIViewanimateWithDuration: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"]strokeEndstrokeEnd为其他任何内容都不会产生任何效果(动画总是看起来一样)。

任何我在这里缺少的提示将不胜感激。

更新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 ,并使用strokeStartstrokeEnd ,并fillColor属性来实现你的效果。 您可能需要两个shapeLayers,一个在另一个之上,但这种方法的优点是shapeLayer的属性可以通过CoreAnimation进行动画处理。

此外,您可以使用这样的hackery在动画块中制作动画,以及https://gist.github.com/nicklockwood/d374033b27c62662ac8d

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM