[翻译] GSProgressView
GSProgressView
本人极不推荐使用drawRect的方式来绘制下载进度条,无论机器的性能怎么高,使用drawRect用于绘制图形都是低效的。
A cute little circular progress view for iOS
一款轻巧的显示圆形进度的的view,用于iOS开发
Installation - 安装
Drag GSProgressView.h and GSProgressView.m into your project.
将GSProgressView.h与GSProgressView.m拖到你的工程当中。
GSProgressView *pv = [[GSProgressView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; pv.color = [UIColor redColor]; pv.progress = 0.6; [myView addSubview:pv];
GSProgressView.h + GSProgressView.m
// // GSProgressView.h // // Created by Simon Whitaker on 14/11/2012. // Copyright (c) 2012 Goo Software Ltd. All rights reserved. // #import <UIKit/UIKit.h> @interface GSProgressView : UIView @property (nonatomic) CGFloat progress; @property (strong, nonatomic) UIColor *color UI_APPEARANCE_SELECTOR; @property (strong, nonatomic) UIColor *tickColor UI_APPEARANCE_SELECTOR; @end
// // GSProgressView.m // // Created by Simon Whitaker on 14/11/2012. // Copyright (c) 2012 Goo Software Ltd. All rights reserved. // #import "GSProgressView.h" #import <QuartzCore/QuartzCore.h> @implementation GSProgressView - (void)commonInit { self.backgroundColor = [UIColor clearColor]; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self commonInit]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self commonInit]; } return self; } - (void)setProgress:(CGFloat)progress { if (progress > 1.0) progress = 1.0; if (progress != _progress) { _progress = progress; [self setNeedsDisplay]; } } - (void)drawRect:(CGRect)rect { if ([self color] == nil) [self setColor:[UIColor blackColor]]; CGPoint center = CGPointMake(rect.size.width/2, rect.size.height/2); CGFloat radius = MIN(rect.size.width, rect.size.height)/2; // Start a path UIBezierPath *path = [UIBezierPath bezierPath]; // Move to centre and draw an arc. [path moveToPoint:center]; [path addArcWithCenter:center radius:radius startAngle:0 - M_PI_2 // zero degrees is east, not north, so subtract pi/2 endAngle:2 * M_PI * [self progress] - M_PI_2 // ditto clockwise:YES]; [path closePath]; // If progress is 1.0, show a tick mark in the centre of the circle if ([self progress] == 1.0) { /* First draw a tick that looks like this: A---F | | | E-------D | | B-----------C (Remember: (0,0) is top left) */ UIBezierPath *tickPath = [UIBezierPath bezierPath]; CGFloat tickWidth = radius/3; [tickPath moveToPoint:CGPointMake(0, 0)]; // A [tickPath addLineToPoint:CGPointMake(0, tickWidth * 2)]; // B [tickPath addLineToPoint:CGPointMake(tickWidth * 3, tickWidth * 2)]; // C [tickPath addLineToPoint:CGPointMake(tickWidth * 3, tickWidth)]; // D [tickPath addLineToPoint:CGPointMake(tickWidth, tickWidth)]; // E [tickPath addLineToPoint:CGPointMake(tickWidth, 0)]; // F [tickPath closePath]; // Now rotate it through -45 degrees... [tickPath applyTransform:CGAffineTransformMakeRotation(-M_PI_4)]; // ...and move it into the right place. [tickPath applyTransform:CGAffineTransformMakeTranslation(radius * 0.43, radius)]; // Account for non-square views CGFloat xOffset = rect.size.width/2 - radius; CGFloat yOffset = rect.size.height/2 - radius; [tickPath applyTransform:CGAffineTransformMakeTranslation(xOffset, yOffset)]; // Add fill color if it's set if (self.tickColor) { [[self tickColor] setFill]; [tickPath fill]; } // Add the tick path to the existing circle path [path appendPath:tickPath]; }; path.usesEvenOddFillRule = YES; [[self color] setFill]; [path fill]; } #pragma mark - Accessibility - (BOOL)isAccessibilityElement { return YES; } - (NSString *)accessibilityLabel { return NSLocalizedString(@"Progress", @"Accessibility label for GSProgressView"); } - (NSString *)accessibilityValue { // Report progress as a percentage, same as UISlider, UIProgressView return [NSString stringWithFormat:@"%d%%", (int)round([self progress] * 100.0)]; } - (UIAccessibilityTraits)accessibilityTraits { return UIAccessibilityTraitUpdatesFrequently; } @end