TYMProgressBarView.m 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. // TYMProgressBarView.m
  3. // TYMProgressBarView
  4. //
  5. // Created by Yiming Tang on 13-6-7.
  6. // Copyright (c) 2013 - 2014 Yiming Tang. All rights reserved.
  7. //
  8. #import "TYMProgressBarView.h"
  9. void strokeRoundedRectInContext(CGContextRef context, CGRect rect, CGFloat lineWidth, CGFloat radius);
  10. void fillRoundedRectInContext(CGContextRef context, CGRect rect, CGFloat radius);
  11. void setRoundedRectPathInContext(CGContextRef context, CGRect rect, CGFloat radius);
  12. @implementation TYMProgressBarView
  13. #pragma mark - Accessors
  14. - (void)setProgress:(CGFloat)newProgress
  15. {
  16. _progress = fmaxf(0.0f, fminf(1.0f, newProgress));
  17. [self setNeedsDisplay];
  18. }
  19. - (void)setbarBorderWidth:(CGFloat)barBorderWidth
  20. {
  21. _barBorderWidth = barBorderWidth;
  22. [self setNeedsDisplay];
  23. }
  24. - (void)setbarBorderColor:(UIColor *)barBorderColor
  25. {
  26. _barBorderColor = barBorderColor;
  27. [self setNeedsDisplay];
  28. }
  29. - (void)setBarInnerBorderWidth:(CGFloat)barInnerBorderWidth
  30. {
  31. _barInnerBorderWidth = barInnerBorderWidth;
  32. [self setNeedsDisplay];
  33. }
  34. - (void)setBarInnerBorderColor:(UIColor *)barInnerBorderColor
  35. {
  36. _barInnerBorderColor = barInnerBorderColor;
  37. [self setNeedsDisplay];
  38. }
  39. - (void)setbarFillColor:(UIColor *)barFillColor
  40. {
  41. _barFillColor = barFillColor;
  42. [self setNeedsDisplay];
  43. }
  44. #pragma mark - Class Methods
  45. + (UIColor *)defaultBarColor
  46. {
  47. return NewWhiteColor;
  48. }
  49. #pragma mark - UIView
  50. - (id)initWithCoder:(NSCoder *)aDecoder
  51. {
  52. if ((self = [super initWithCoder:aDecoder])) {
  53. [self initialize];
  54. }
  55. return self;
  56. }
  57. - (id)initWithFrame:(CGRect)aFrame
  58. {
  59. if ((self = [super initWithFrame:aFrame])) {
  60. [self initialize];
  61. }
  62. return self;
  63. }
  64. - (void)drawRect:(CGRect)rect
  65. {
  66. CGContextRef context = UIGraphicsGetCurrentContext();
  67. CGContextSaveGState(context);
  68. CGContextSetAllowsAntialiasing(context, TRUE);
  69. CGRect currentRect = rect;
  70. CGFloat radius;
  71. CGFloat halfLineWidth;
  72. // Background
  73. if (self.backgroundColor) {
  74. radius = currentRect.size.height / 2;
  75. [self.barBackgroundColor setFill];
  76. fillRoundedRectInContext(context, currentRect, radius);
  77. }
  78. // Border
  79. if (self.barBorderColor && self.barBorderWidth > 0.0f) {
  80. // Inset, because a stroke is centered on the path
  81. // See http://stackoverflow.com/questions/10557157/drawing-rounded-rect-in-core-graphics
  82. halfLineWidth = self.barBorderWidth / 2;
  83. currentRect = CGRectInset(currentRect, halfLineWidth, halfLineWidth);
  84. radius = currentRect.size.height / 2;
  85. [self.barBorderColor setStroke];
  86. strokeRoundedRectInContext(context, currentRect, self.barBorderWidth, radius);
  87. currentRect = CGRectInset(currentRect, halfLineWidth, halfLineWidth);
  88. }
  89. // Padding
  90. currentRect = CGRectInset(currentRect, self.barInnerPadding, self.barInnerPadding);
  91. BOOL hasInnerBorder = NO;
  92. // Inner border
  93. if (self.barInnerBorderColor && self.barInnerBorderWidth > 0.0f) {
  94. hasInnerBorder = YES;
  95. halfLineWidth = self.barInnerBorderWidth / 2;
  96. currentRect = CGRectInset(currentRect, halfLineWidth, halfLineWidth);
  97. radius = currentRect.size.height / 2;
  98. // progress
  99. currentRect.size.width *= self.progress;
  100. currentRect.size.width = MAX(currentRect.size.width, 2 * radius);
  101. [self.barInnerBorderColor setStroke];
  102. strokeRoundedRectInContext(context, currentRect, self.barInnerBorderWidth, radius);
  103. currentRect = CGRectInset(currentRect, halfLineWidth, halfLineWidth);
  104. }
  105. // Fill
  106. if (self.barFillColor) {
  107. radius = currentRect.size.height / 2;
  108. // recalculate width
  109. if (!hasInnerBorder) {
  110. currentRect.size.width *= self.progress;
  111. currentRect.size.width = MAX(currentRect.size.width, 2 * radius);
  112. }
  113. [self.barFillColor setFill];
  114. fillRoundedRectInContext(context, currentRect, radius);
  115. }
  116. // Restore the context
  117. CGContextRestoreGState(context);
  118. }
  119. #pragma mark - Private
  120. - (void)initialize
  121. {
  122. self.contentMode = UIViewContentModeRedraw;
  123. self.backgroundColor = [UIColor clearColor];
  124. _progress = 0.0f;
  125. _barBorderWidth = 0.7f;
  126. _barBorderColor = [[self class] defaultBarColor];
  127. _barFillColor = NewThemeColor;//self.barBorderColor;
  128. _barInnerBorderWidth = 0.0f;
  129. _barInnerBorderColor = nil;
  130. _barInnerPadding = 0.0f;
  131. _barBackgroundColor = [UIColor whiteColor];
  132. }
  133. @end
  134. #pragma mark - Drawing Functions
  135. void strokeRoundedRectInContext(CGContextRef context, CGRect rect, CGFloat lineWidth, CGFloat radius)
  136. {
  137. CGContextSetLineWidth(context, lineWidth);
  138. setRoundedRectPathInContext(context, rect, radius);
  139. CGContextStrokePath(context);
  140. }
  141. void fillRoundedRectInContext(CGContextRef context, CGRect rect, CGFloat radius)
  142. {
  143. setRoundedRectPathInContext(context, rect, radius);
  144. CGContextFillPath(context);
  145. }
  146. void setRoundedRectPathInContext(CGContextRef context, CGRect rect, CGFloat radius)
  147. {
  148. CGContextBeginPath(context);
  149. CGContextMoveToPoint(context, CGRectGetMinX(rect), CGRectGetMidY(rect));
  150. CGContextAddArcToPoint(context, CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetMidX(rect), CGRectGetMinY(rect), radius);
  151. CGContextAddArcToPoint(context, CGRectGetMaxX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMidY(rect), radius);
  152. CGContextAddArcToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect), CGRectGetMidX(rect), CGRectGetMaxY(rect), radius);
  153. CGContextAddArcToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMidY(rect), radius);
  154. CGContextClosePath(context);
  155. }