我正在尝试模拟Apple在iOS 7中下载应用程序时作为进度指示器的效果,有点像饼图:
我的代码很顺利。我可以给它一个值,它会更新到那个。
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGFloat radius = CGRectGetWidth(self.frame) / 2;
CGFloat inset = 1;
CAShapeLayer *ring = [CAShapeLayer layer];
ring.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)cornerRadius:radius-inset].CGPath;
ring.fillColor = [UIColor clearColor].CGColor;
ring.strokeColor = [UIColor whiteColor].CGColor;
ring.lineWidth = 2;
self.innerPie = [CAShapeLayer layer];
inset = radius/2;
self.innerPie.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
cornerRadius:radius-inset].CGPath;
self.innerPie.fillColor = [UIColor clearColor].CGColor;
self.innerPie.strokeColor = [UIColor whiteColor].CGColor;
self.innerPie.lineWidth = (radius-inset)*2;
[self.layer addSublayer:ring];
[self.layer addSublayer:self.innerPie];
self.progress = 0.0;
self.innerPie.hidden = YES;
}
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated {
if (animated) {
self.innerPie.hidden = NO;
self.innerPie.strokeEnd = progress;
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
pathAnimation.duration = 0.5;
pathAnimation.fromValue = [NSNumber numberWithFloat:self.progress];
pathAnimation.toValue = [NSNumber numberWithFloat:progress];
[self.innerPie addAnimation:pathAnimation forKey:@"strokeEnd"];
}
else {
[CATransaction setDisableActions:YES];
[CATransaction begin];
self.innerPie.hidden = NO;
self.innerPie.strokeEnd = progress;
[CATransaction commit];
}
self.progress = progress;
}
我的问题在于在动画中间更新进度。例如,如果我正在下载文件并且进度从0.1跳到0.2(10%到20%),我想要设置动画。说我给它一个0.5秒的动画。如果在0.5秒动画中0.2秒跳到0.4(40%)怎么办?
使用我当前的代码,它会在第一个动画(20%)中跳转到应该结束的位置(当它应该有动画时),然后再次开始动画到40%。
我希望它几乎将toValue
更新为0.4。至少那是我想要的。从概念上讲,我希望它能够在不中断之前值的情况下继续将动画转向新值。平稳,说得简单。
我将如何做到这一点?
我知道有这样的库可以做到这一点。我想为学习目的而自己做。
答案 0 :(得分:3)
你应该替换
pathAnimation.fromValue = [NSNumber numberWithFloat:self.progress];
with:
pathAnimation.fromValue = [NSNumber numberWithFloat:[self.innerPie.presentationLayer strokeEnd]];
最初,[self.innerPie.presentationLayer strokeEnd]]
将为1,因此您需要将初始值设置为0.将这两行添加到您创建“innerPie”的位置:
self.innerPie.strokeStart = 0;
self.innerPie.strokeEnd = 0;
我已经测试过并且有效。