我有一个进度条,我使用重复计时器进行动画制作。它工作得很好,除了动画不像使用核心动画那么顺畅。如果有人有任何建议如何使用核心动画实现它,我将不胜感激!我没有问题使用核心动画来处理更简单的东西,但是动画渐变等让我很难过。
我的代码在这里 -
-(id)initWithWidth:(float)theWidth radius:(float)theRadius progress:(float)theProgress
{
self = [super initWithFrame:CGRectMake(0, 0, theWidth, theRadius * 2)];
if (self) {
_progressBarWidth = theWidth;
_radius = theRadius;
_progress = (float)theProgress;
self.backgroundColor = [UIColor clearColor];
}
return self;
}
-(void)setProgress:(float)theProgress
{
_progress = theProgress;
[self setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect
{
// gradient for blue background (pale blue -> dark blue)
float colours[] = {0.0, 135.0 / 255.0, 237.0 / 255.0, 1.0, 1.0 / 255.0, 24.0 / 255.0, 140.0 / 255.0, 1.0};
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
size_t num_locations = 2;
CGFloat locations[2] = {0.0, 1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colours, locations, num_locations);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextMoveToPoint(context, _radius, 0.0);
CGContextAddArcToPoint(context, _progressBarWidth, 0.0, _progressBarWidth, _radius, _radius);
CGContextAddArcToPoint(context, _progressBarWidth, 2.0 * _radius, _progressBarWidth - _radius, 2.0 * _radius, _radius);
CGContextAddArcToPoint(context, 0.0, 2.0 * _radius, 0.0, _radius, _radius);
CGContextAddArcToPoint(context, 0.0, 0.0, _radius, 0.0, _radius);
CGContextClosePath(context);
CGContextClip(context);
CGPoint startPoint = CGPointMake(_progressBarWidth / 2.0, 0.0);
CGPoint endPoint = CGPointMake(_progressBarWidth / 2.0, 2.0 * _radius);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);
CGColorSpaceRelease(baseSpace);
CGContextRestoreGState(context);
// gradient for progressed element (pale yellow -> dark yellow)
float colours2[] = {252.0 / 255.0, 224.0 / 255.0, 0.0, 1.0, 246.0 / 255.0, 191.0 / 255.0, 0.0, 1.0};
baseSpace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColorComponents(baseSpace, colours2, locations, num_locations);
context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// this defines an overall clipping path for the yellow bar (it's got a square end which can protrude when it's near 100%)
CGContextMoveToPoint(context, _radius, kDefaultLineWidth);
CGContextAddArcToPoint(context, _progressBarWidth - kDefaultLineWidth, kDefaultLineWidth, _progressBarWidth - kDefaultLineWidth, _radius, _radius - kDefaultLineWidth);
CGContextAddArcToPoint(context, _progressBarWidth - kDefaultLineWidth, 2.0 * _radius - kDefaultLineWidth, _progressBarWidth - _radius, 2.0 * _radius - kDefaultLineWidth, _radius - kDefaultLineWidth);
CGContextAddArcToPoint(context, kDefaultLineWidth, 2.0 * _radius - kDefaultLineWidth, kDefaultLineWidth, _radius, _radius - kDefaultLineWidth);
CGContextAddArcToPoint(context, kDefaultLineWidth, kDefaultLineWidth, _radius, kDefaultLineWidth, _radius - kDefaultLineWidth);
CGContextClosePath(context);
CGContextClip(context);
// now draw the yellow bar
float progressWidth = _progress * _progressBarWidth;
CGContextMoveToPoint(context, progressWidth, kDefaultLineWidth);
CGContextAddArcToPoint(context, kDefaultLineWidth, kDefaultLineWidth, kDefaultLineWidth, _radius, _radius - kDefaultLineWidth);
CGContextAddArcToPoint(context, kDefaultLineWidth, 2.0 * _radius - kDefaultLineWidth, _radius, 2.0 * _radius - kDefaultLineWidth, _radius - kDefaultLineWidth);
CGContextAddLineToPoint(context, progressWidth, 2.0 * _radius - kDefaultLineWidth);
CGContextClosePath(context);
CGContextClip(context);
startPoint = CGPointMake(progressWidth / 2.0, kDefaultLineWidth);
endPoint = CGPointMake(progressWidth / 2.0, 2.0 * _radius - kDefaultLineWidth);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);
CGColorSpaceRelease(baseSpace);
CGContextRestoreGState(context);
// draw the scale
CGContextSetLineWidth(context, 0.25f);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
float div = _progressBarWidth / 10;
for (float i = 1; i < 10; i++) {
CGContextMoveToPoint(context, div * i, 0.25);
CGContextAddLineToPoint(context, div * i, _radius * 2.0 + 1.75);
CGContextDrawPath(context, kCGPathStroke);
}
CGContextSetStrokeColorWithColor(context, [UIColor darkGrayColor].CGColor);
for (float i = 1; i < 10; i++) {
CGContextMoveToPoint(context, div * i - 0.5, 0.25);
CGContextAddLineToPoint(context, div * i - 0.5, _radius * 2.0 + 1.75);
CGContextDrawPath(context, kCGPathStroke);
}
}
进度条的图像为0%&amp; 75%:
感谢您的帮助。
答案 0 :(得分:0)
在动画期间,您不得多次调用绘图代码。 在您的情况下,最简单的方法是使用两个视图:一个用于开始状态,一个用于最终状态。 您可以将它们作为子视图添加到进度条视图中。 然后,您只绘制两次视图(甚至使用就绪图像)并为视图框设置动画。
E.g。
...
[self addSubview:endView];
[self addSubview:startView];
...
-(void)animateProgressFrom:(float)fromValue to:(float)toValue
{
CGRect startRect = self.bounds;
startRect.size.width *= fromValue;
startView.frame = startRect;
[UIView animateWithDuration:duration animations:^{
CGRect endRect = self.bounds;
endRect.size.width *= toValue;
startView.frame = endRect;
}];
}
它可以是任何两个图像,而不是必要的渐变颜色。
答案 1 :(得分:0)
我最终采用了一种更简单的方法,将剪裁的UIViews&amp;使用animateWithDuration:动画:
这是主要代码 -
-(id)initWithWidth:(float)theWidth radius:(float)theRadius progress:(float)theProgress duration:(float)theDuration
{
self = [super initWithFrame:CGRectMake(0, 0, theWidth, theRadius * 2)];
if (self) {
_progressBarWidth = theWidth;
_radius = theRadius;
_progress = (float)theProgress;
_animationDuration = theDuration;
self.backgroundColor = [UIColor clearColor];
// make the view the right shape
self.layer.cornerRadius = _radius;
self.clipsToBounds = YES;
}
return self;
}
-(void)showProgress
{
// draw the main background (which is seen as the outline)
float tempColours[] = {0.0, 135.0 / 255.0, 237.0 / 255.0, 1.0, 1.0 / 255.0, 24.0 / 255.0, 140.0 / 255.0, 1.0};
NSMutableArray *colours = [NSMutableArray array];
for (int i = 0; i < 8; i++) {
[colours addObject:[NSNumber numberWithFloat:tempColours[i]]];
}
// GradientView is a class which gives me UIViews with a gradient fill
GradientView *mainBGView = [[[GradientView alloc] initWithWidth:_progressBarWidth height:2.0 * _radius colours:colours] autorelease];
mainBGView.frame = CGRectMake(0, 0, _progressBarWidth, 2.0 * _radius);
[self addSubview:mainBGView];
// add the sub-background and progress bar element
UIView *clippingContainerView = [[[UIView alloc] initWithFrame:CGRectMake(kDefaultLineWidth, kDefaultLineWidth, _progressBarWidth - 2.0 * kDefaultLineWidth, 2.0 * _radius - 2.0 * kDefaultLineWidth)] autorelease];
clippingContainerView.backgroundColor = [UIColor clearColor];
clippingContainerView.layer.cornerRadius = _radius - kDefaultLineWidth;
clippingContainerView.clipsToBounds = YES;
float tempBackgroundColours[] = {152.0 / 255.0, 152.0 / 255.0, 152.0 / 255.0, 1.0, 216.0 / 255.0, 216.0 / 255.0, 216.0 / 255.0, 1.0};
NSMutableArray *backgroundColours = [NSMutableArray array];
for (int i = 0; i < 8; i++) {
[backgroundColours addObject:[NSNumber numberWithFloat:tempBackgroundColours[i]]];
}
GradientView *greyBGView = [[[GradientView alloc] initWithWidth:_progressBarWidth - 2.0 * kDefaultLineWidth height:2.0 * _radius - 2.0 * kDefaultLineWidth colours:backgroundColours] autorelease];
greyBGView.frame = CGRectMake(0, 0, _progressBarWidth - 2.0 * kDefaultLineWidth, 2.0 * _radius - 2.0 * kDefaultLineWidth);
[clippingContainerView addSubview:greyBGView];
float tempProgressBarColours[] = {251.0 / 255.0, 215.0 / 255.0, 17.0 / 255.0, 1.0, 244.0 / 255.0, 184.0 / 255.0, 2.0 / 255.0, 1.0};
NSMutableArray *progressBarColours = [NSMutableArray array];
for (int i = 0; i < 8; i++) {
[progressBarColours addObject:[NSNumber numberWithFloat:tempProgressBarColours[i]]];
}
GradientView *barGradientView = [[[GradientView alloc] initWithWidth:1.0 height:2.0 * _radius - 2.0 * kDefaultLineWidth colours:progressBarColours] autorelease];
barGradientView.frame = CGRectMake(0, 0, 1, 2.0 * _radius); // start with progress bar too narrow to see
[clippingContainerView addSubview:barGradientView];
[self addSubview:clippingContainerView];
// animate the progress bar
float progressWidth = _progress * _progressBarWidth; // how wide it is at end of animation
[UIView animateWithDuration:_animationDuration
animations:^{
barGradientView.frame = CGRectMake(0, 0, progressWidth, 2.0 * _radius);
}];
}
非常直接,&amp;做得很好。