Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

language: objective-c
cache: cocoapods
osx_image: xcode8.1
osx_image: xcode8.3
# podfile: Example/Podfile

rvm:
Expand All @@ -15,5 +15,5 @@ before_install:
install:
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
script:
- set -o pipefail && xcodebuild test -workspace Example/MBCircularProgressBar.xcworkspace -scheme MBCircularProgressBar-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c
- set -o pipefail && xcodebuild clean test -workspace Example/MBCircularProgressBar.xcworkspace -scheme MBCircularProgressBar-Example -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6s' | xcpretty -c
- pod lib lint --quick
16 changes: 16 additions & 0 deletions Pod/Classes/MBCircularProgressBarLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

@import QuartzCore;

typedef NS_ENUM(NSInteger, MBCircularProgressBarAppearanceType) {
MBCircularProgressBarAppearanceTypeOverlaysEmptyLine = 0,
MBCircularProgressBarAppearanceTypeAboveEmptyLine = 1,
MBCircularProgressBarAppearanceTypeUnderEmptyLine = 2
};

/**
* The MBCircularProgressBarLayer class is a CALayer subclass that represents the underlying layer
* of MBCircularProgressBarView.
Expand All @@ -24,6 +30,11 @@
*/
@property (nonatomic,assign) CGFloat progressRotationAngle;

/**
* Progress bar appearance type
*/
@property (nonatomic,assign) MBCircularProgressBarAppearanceType progressAppearanceType;

/**
* The value of the progress bar
*/
Expand All @@ -34,6 +45,11 @@
*/
@property (nonatomic,assign) CGFloat maxValue;

/**
* Padding from borders
*/
@property (nonatomic,assign) CGFloat borderPadding;

/**
* Animation duration in seconds
*/
Expand Down
57 changes: 37 additions & 20 deletions Pod/Classes/MBCircularProgressBarLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
@implementation MBCircularProgressBarLayer
@dynamic value;
@dynamic maxValue;
@dynamic borderPadding;
@dynamic valueFontSize;
@dynamic unitString;
@dynamic unitFontSize;
Expand All @@ -28,6 +29,7 @@ @implementation MBCircularProgressBarLayer
@dynamic progressCapType;
@dynamic fontColor;
@dynamic progressRotationAngle;
@dynamic progressAppearanceType;
@dynamic decimalPlaces;
@dynamic valueDecimalFontSize;
@dynamic unitFontName;
Expand All @@ -48,28 +50,38 @@ - (void) drawInContext:(CGContextRef) context{

UIGraphicsPushContext(context);

CGSize size = CGRectIntegral(CGContextGetClipBoundingBox(context)).size;
[self drawEmptyBar:size context:context];
[self drawProgressBar:size context:context];
CGRect rect = CGContextGetClipBoundingBox(context);
rect = CGRectIntegral(CGRectInset(rect, self.borderPadding, self.borderPadding));

[self drawEmptyBar:rect context:context];
[self drawProgressBar:rect context:context];

if (self.showValueString){
[self drawText:size context:context];
[self drawText:rect context:context];
}

UIGraphicsPopContext();
}

- (void)drawEmptyBar:(CGSize)rectSize context:(CGContextRef)c{
- (void)drawEmptyBar:(CGRect)rect context:(CGContextRef)c{

if(self.emptyLineWidth <= 0){
return;
}

CGMutablePathRef arc = CGPathCreateMutable();
CGPoint center = {CGRectGetMidX(rect), CGRectGetMidY(rect)};
CGFloat radius = MIN(CGRectGetWidth(rect), CGRectGetHeight(rect))/2;
if (self.progressAppearanceType == MBCircularProgressBarAppearanceTypeOverlaysEmptyLine) {
radius = radius - MAX(self.emptyLineWidth, self.progressLineWidth)/2.f;
} else if (self.progressAppearanceType == MBCircularProgressBarAppearanceTypeAboveEmptyLine) {
radius = radius - self.progressLineWidth - self.emptyLineWidth/2.f;
} else {
radius = radius - self.emptyLineWidth/2.f;
}

CGMutablePathRef arc = CGPathCreateMutable();
CGPathAddArc(arc, NULL,
rectSize.width/2, rectSize.height/2,
MIN(rectSize.width,rectSize.height)/2 - self.progressLineWidth,
center.x, center.y, radius,
(self.progressAngle/100.f)*M_PI-((-self.progressRotationAngle/100.f)*2.f+0.5)*M_PI,
-(self.progressAngle/100.f)*M_PI-((-self.progressRotationAngle/100.f)*2.f+0.5)*M_PI,
YES);
Expand All @@ -92,16 +104,24 @@ - (void)drawEmptyBar:(CGSize)rectSize context:(CGContextRef)c{
CGPathRelease(strokedArc);
}

- (void)drawProgressBar:(CGSize)rectSize context:(CGContextRef)c{
- (void)drawProgressBar:(CGRect)rect context:(CGContextRef)c{
if(self.progressLineWidth <= 0){
return;
}

CGMutablePathRef arc = CGPathCreateMutable();
CGPoint center = {CGRectGetMidX(rect), CGRectGetMidY(rect)};
CGFloat radius = MIN(CGRectGetWidth(rect), CGRectGetHeight(rect))/2;
if (self.progressAppearanceType == MBCircularProgressBarAppearanceTypeOverlaysEmptyLine) {
radius = radius - MAX(self.emptyLineWidth, self.progressLineWidth)/2.f;
} else if (self.progressAppearanceType == MBCircularProgressBarAppearanceTypeAboveEmptyLine) {
radius = radius - self.progressLineWidth/2.f;
} else {
radius = radius - self.emptyLineWidth - self.progressLineWidth/2.f;
}

CGMutablePathRef arc = CGPathCreateMutable();
CGPathAddArc(arc, NULL,
rectSize.width/2, rectSize.height/2,
MIN(rectSize.width,rectSize.height)/2 - self.progressLineWidth,
center.x, center.y, radius,
(self.progressAngle/100.f)*M_PI-((-self.progressRotationAngle/100.f)*2.f+0.5)*M_PI-(2.f*M_PI)*(self.progressAngle/100.f)*(100.f-100.f*self.value/self.maxValue)/100.f,
-(self.progressAngle/100.f)*M_PI-((-self.progressRotationAngle/100.f)*2.f+0.5)*M_PI,
YES);
Expand All @@ -123,14 +143,11 @@ - (void)drawProgressBar:(CGSize)rectSize context:(CGContextRef)c{
CGPathRelease(strokedArc);
}

- (void)drawText:(CGSize)rectSize context:(CGContextRef)c
{


- (void)drawText:(CGRect)rect context:(CGContextRef)c{
NSMutableParagraphStyle* textStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
textStyle.alignment = NSTextAlignmentLeft;

CGFloat valueFontSize = self.valueFontSize == -1 ? rectSize.height/5 : self.valueFontSize;
CGFloat valueFontSize = self.valueFontSize == -1 ? CGRectGetHeight(rect)/5 : self.valueFontSize;

NSDictionary* valueFontAttributes = @{NSFontAttributeName: [UIFont fontWithName: self.valueFontName size:valueFontSize], NSForegroundColorAttributeName: self.fontColor, NSParagraphStyleAttributeName: textStyle};

Expand Down Expand Up @@ -158,7 +175,7 @@ - (void)drawText:(CGSize)rectSize context:(CGContextRef)c

// ad the unit only if specified
if (self.showUnitString) {
NSDictionary* unitFontAttributes = @{NSFontAttributeName: [UIFont fontWithName: self.unitFontName size:self.unitFontSize == -1 ? rectSize.height/7 : self.unitFontSize], NSForegroundColorAttributeName: self.fontColor, NSParagraphStyleAttributeName: textStyle};
NSDictionary* unitFontAttributes = @{NSFontAttributeName: [UIFont fontWithName: self.unitFontName size:self.unitFontSize == -1 ? CGRectGetHeight(rect)/7 : self.unitFontSize], NSForegroundColorAttributeName: self.fontColor, NSParagraphStyleAttributeName: textStyle};

NSAttributedString* unit =
[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@", self.unitString] attributes:unitFontAttributes];
Expand All @@ -167,8 +184,8 @@ - (void)drawText:(CGSize)rectSize context:(CGContextRef)c

CGSize percentSize = [text size];
CGPoint textCenter = CGPointMake(
rectSize.width/2-percentSize.width/2 + self.textOffset.x,
rectSize.height/2-percentSize.height/2 + self.textOffset.y
CGRectGetMidX(rect)-percentSize.width/2 + self.textOffset.x,
CGRectGetMidY(rect)-percentSize.height/2 + self.textOffset.y
);

[text drawAtPoint:textCenter];
Expand Down
10 changes: 10 additions & 0 deletions Pod/Classes/MBCircularProgressBarView.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ IB_DESIGNABLE
*/
@property (nonatomic,assign) IBInspectable CGFloat maxValue;

/**
* Padding from borders
*/
@property (nonatomic,assign) IBInspectable CGFloat borderPadding;

/*
* Number of decimal places of the value [0,∞)
*/
Expand Down Expand Up @@ -75,6 +80,11 @@ IB_DESIGNABLE
*/
@property (nonatomic,strong) IBInspectable UIColor *fontColor;

/**
* Progress bar appearance type
*/
@property (nonatomic,assign) IBInspectable NSInteger progressAppearanceType;

/**
* Progress bar rotation (Clockewise) [0,100]
*/
Expand Down
44 changes: 35 additions & 9 deletions Pod/Classes/MBCircularProgressBarView.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

@implementation MBCircularProgressBarView

- (instancetype)initWithCoder:(NSCoder *)coder
{
-(instancetype)initWithCoder:(NSCoder *)coder{
self = [super initWithCoder:coder];
if (self) {
[self initView:[self frame]];
Expand All @@ -28,8 +27,7 @@ -(instancetype)init{
return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
-(instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self initView:frame];
Expand All @@ -40,10 +38,15 @@ - (instancetype)initWithFrame:(CGRect)frame
-(void)initView:(CGRect)frame{
//Without setting the content scale factor the layer would be pixelated
[self setContentScaleFactor:[[UIScreen mainScreen] scale]];


//This mode forces redrawing when bounds change (e.g. bounds change in animation)
[self setContentMode:UIViewContentModeRedraw];

[self setUnitString:@"%"];
[self setValue:0.f];
[self setMaxValue:100.f];
[self setBorderPadding:1.f];
[self setProgressAppearanceType:0];
[self setProgressRotationAngle:0.f];
[self setProgressStrokeColor:[UIColor orangeColor]];
[self setProgressColor:[UIColor orangeColor]];
Expand Down Expand Up @@ -103,6 +106,14 @@ -(CGFloat)maxValue{
return self.progressLayer.maxValue;
}

-(void)setBorderPadding:(CGFloat)borderPadding{
self.progressLayer.borderPadding = borderPadding;
}

-(CGFloat)borderPadding{
return self.progressLayer.borderPadding;
}

-(void)setProgressLineWidth:(CGFloat)width{
self.progressLayer.progressLineWidth = width;
}
Expand Down Expand Up @@ -191,11 +202,27 @@ -(CGFloat)progressAngle{
return self.progressLayer.progressAngle;
}

-(void)setProgressAppearanceType:(NSInteger)progressAppearanceType{
self.progressLayer.progressAppearanceType = [self safeProgressAppearanceType:progressAppearanceType];
}

-(NSInteger)progressAppearanceType{
return self.progressLayer.progressAppearanceType;
}

-(MBCircularProgressBarAppearanceType)safeProgressAppearanceType:(NSInteger)progressAppearanceType{
if(MBCircularProgressBarAppearanceTypeOverlaysEmptyLine <= progressAppearanceType && progressAppearanceType <= MBCircularProgressBarAppearanceTypeUnderEmptyLine){
return (MBCircularProgressBarAppearanceType)progressAppearanceType;
}

return MBCircularProgressBarAppearanceTypeOverlaysEmptyLine;
}

-(void)setProgressRotationAngle:(CGFloat)progressRootationAngle{
self.progressLayer.progressRotationAngle = progressRootationAngle;
}

-(CGFloat)progressRootationAngle{
-(CGFloat)progressRotationAngle{
return self.progressLayer.progressRotationAngle;
}

Expand All @@ -211,7 +238,7 @@ -(void)setEmptyCapType:(NSInteger)emptyCapType{
self.progressLayer.emptyCapType = [self safeCapType:emptyCapType];
}

-(NSInteger)EmptyCapType{
-(NSInteger)emptyCapType{
return self.progressLayer.emptyCapType;
}

Expand Down Expand Up @@ -285,8 +312,7 @@ -(MBCircularProgressBarLayer*)progressLayer{
return layer;
}

+ (Class) layerClass
{
+ (Class) layerClass {
return [MBCircularProgressBarLayer class];
}

Expand Down