// // CCProgressView.h // Demo // // Created by leao on 2017/8/7. // Copyright © 2017年 zaodao. All rights reserved. // #import <UIKit/UIKit.h> typedef NS_ENUM(NSInteger, CCProgressViewStyle) { CCProgressViewStyleCircle, // 圆形进度条 CCProgressViewStyleBar, // 条形进度条 CCProgressViewStyleDefault = CCProgressViewStyleCircle, }; @interface CCProgressView : UIView @property(nonatomic, assign, setter=setProgress:) CGFloat progress; // 0.0 ~ 1.0 @property(nonatomic, assign) CCProgressViewStyle progressViewStyle; // 进度条style @property(nonatomic, strong) UIColor *trackTintColor; // 进度条背景色 @property(nonatomic, strong) UIColor *progressTintColor; // 进度条颜色 @property(nonatomic, strong) UIColor *progressFullTintColor; // 进度完成时progressTint的颜色 @property(nonatomic, assign) CGFloat lineWidth; // 绘制progress宽度 default: 10 @property(nonatomic, assign) CGFloat trackerWidth; // 绘制progress宽度 default: 10 // CCProgressViewStyleCircle 有效 @property(nonatomic, strong) UIColor *fillColor; // 中心颜色 @property(nonatomic, assign) BOOL clockwise; // 是否是顺时针 default: YES @property(nonatomic, assign) CGFloat startAngle; // 进度条开始angle, default: -M_PI/2.0 @property (nonatomic, strong) UIButton *centerBtn; // 记录进度的Label @property (nonatomic, strong) UIColor *labelbackgroundColor; // Label的背景色 默认clearColor @property (nonatomic, strong) UIColor *textColor; // Label的字体颜色 默认黑色 @property (nonatomic, strong) UIFont *textFont; // Label的字体大小 默认15 - (void)setProgress:(CGFloat)progress; - (void)setProgress:(CGFloat)progress animated:(BOOL)animated; @end
// // CCProgressView.m // Demo // // Created by leao on 2017/8/7. // Copyright © 2017年 zaodao. All rights reserved. // #import "CCProgressView.h" #import <pop/POP.h> #import <objc/runtime.h> #import <ReactiveCocoa/ReactiveCocoa.h> #define kCCProgressFillColor [UIColor clearColor] #define kCCProgressTintColor RGBCOLOR(214, 88, 45) #define kCCTrackTintColor RGBCOLOR(243, 212, 187) #define PROGRESS_WIDTH self.frame.size.width #define PROGRESS_HEIGHT self.frame.size.height #define kAnimTimeInterval 2 @interface CCProgressView () @property(nonatomic, strong) CAShapeLayer *trackLayer; @property(nonatomic, strong) CAShapeLayer *progressLayer; @end @implementation CCProgressView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initSubviews]; } return self; } - (instancetype)init { self = [super init]; if (self) { [self initSubviews]; } return self; } #pragma mark - private - (void)initSubviews { _progressViewStyle = CCProgressViewStyleDefault; _progressTintColor = kCCProgressTintColor; _trackTintColor = kCCTrackTintColor; _lineWidth = 10; _trackerWidth = 10; _fillColor = kCCProgressFillColor; _clockwise = YES; _startAngle = - M_PI / 2.0; self.backgroundColor = [UIColor clearColor]; self.trackLayer = [CAShapeLayer layer]; self.trackLayer.lineCap = kCALineCapButt; self.trackLayer.lineJoin = kCALineCapButt; self.trackLayer.lineWidth = _lineWidth; self.trackLayer.fillColor = nil; self.trackLayer.strokeColor = _trackTintColor.CGColor; self.trackLayer.frame = self.bounds; [self.layer addSublayer:self.trackLayer]; self.progressLayer = [CAShapeLayer layer]; self.progressLayer.lineCap = kCALineCapButt; self.progressLayer.lineJoin = kCALineCapButt; self.progressLayer.lineWidth = _trackerWidth; self.progressLayer.fillColor = _fillColor.CGColor; self.progressLayer.strokeColor = _progressTintColor.CGColor; self.progressLayer.frame = self.bounds; [self.layer addSublayer:self.progressLayer]; self.progressLayer.strokeEnd = 0.0; [self addSubview:self.centerBtn]; } - (void)layoutSubviews { [super layoutSubviews]; [self updateLayerPath]; } #pragma mark - private - (UIButton *)centerBtn { if(!_centerBtn) { _centerBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, PROGRESS_WIDTH - 14, PROGRESS_HEIGHT - 14)]; _centerBtn.center = CGPointMake(PROGRESS_WIDTH/2, PROGRESS_HEIGHT/2); _centerBtn.titleLabel.textAlignment = NSTextAlignmentCenter; _centerBtn.layer.cornerRadius = _centerBtn.width/2; _centerBtn.backgroundColor = RGBCOLOR(246, 227, 204); _centerBtn.titleLabel.adjustsFontSizeToFitWidth = YES; _centerBtn.userInteractionEnabled = NO; _centerBtn.layer.masksToBounds = YES; } return _centerBtn; } - (void)updateLayerPath { if (_progressViewStyle == CCProgressViewStyleCircle) { self.trackLayer.frame = self.bounds; self.progressLayer.frame = self.bounds; CGFloat radius = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? (CGRectGetHeight(self.frame) - _lineWidth) / 2.0 : (CGRectGetWidth(self.frame) - _lineWidth) / 2.0; UIBezierPath *bezierPath = [UIBezierPath bezierPathWithArcCenter:self.progressLayer.position radius:radius startAngle:_startAngle endAngle:_clockwise ? _startAngle + 2 * M_PI : _startAngle - 2 * M_PI clockwise:_clockwise]; self.trackLayer.path = bezierPath.CGPath; self.progressLayer.path = bezierPath.CGPath; } else { self.trackLayer.frame = CGRectMake(0, (CGRectGetHeight(self.frame) - _lineWidth) / 2.0, CGRectGetWidth(self.frame), _lineWidth); self.progressLayer.frame = self.trackLayer.frame; UIBezierPath *bezierPath = [UIBezierPath bezierPath]; [bezierPath moveToPoint:CGPointMake(0, self.progressLayer.position.y)]; [bezierPath addLineToPoint:CGPointMake(CGRectGetWidth(self.frame), self.progressLayer.position.y)]; self.trackLayer.path = bezierPath.CGPath; self.progressLayer.path = bezierPath.CGPath; } } #pragma mark - setter - (void)setTrackTintColor:(UIColor *)trackTintColor { _trackTintColor = trackTintColor; self.trackLayer.strokeColor = trackTintColor.CGColor; } - (void)setProgressTintColor:(UIColor *)progressTintColor { _progressTintColor = progressTintColor; self.progressLayer.strokeColor = progressTintColor.CGColor; } - (void)setProgressFullTintColor:(UIColor *)progressFullTintColor { _progressFullTintColor = progressFullTintColor; if (self.progressLayer.strokeEnd >= 1.0) { self.progressLayer.strokeEnd = 1.0; self.progressLayer.strokeColor = _progressFullTintColor.CGColor; } } - (void)setLineWidth:(CGFloat)lineWidth { _lineWidth = lineWidth; // self.trackLayer.lineWidth = lineWidth; self.progressLayer.lineWidth = lineWidth; if (_progressViewStyle != CCProgressViewStyleCircle) { [self updateLayerPath]; } } - (void)setTrackerWidth:(CGFloat)trackerWidth { _trackerWidth = trackerWidth; self.trackLayer.lineWidth = _trackerWidth; if (_progressViewStyle != CCProgressViewStyleCircle) { [self updateLayerPath]; } } #pragma mark - setter (CCProgressViewStyleCircle) - (void)setFillColor:(UIColor *)fillColor { _fillColor = fillColor; self.progressLayer.fillColor = fillColor.CGColor; } - (void)setClockwise:(BOOL)clockwise { _clockwise = clockwise; [self updateLayerPath]; } - (void)setStartAngle:(CGFloat)startAngle { _startAngle = startAngle; [self updateLayerPath]; } - (void)setProgress:(CGFloat)progress { [self setProgress:progress animated:NO]; } - (void)setProgress:(CGFloat)progress animated:(BOOL)animated { if (animated) { // 这里的动画可以直接使用CABasicAnimation POPBasicAnimation *basicAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd]; if (basicAnim) { basicAnim.duration = kAnimTimeInterval; basicAnim.toValue = @(progress); } else { basicAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd]; basicAnim.fromValue = @(self.progressLayer.strokeEnd); basicAnim.toValue = @(progress); basicAnim.duration = 4 * kAnimTimeInterval; basicAnim.removedOnCompletion = YES; } @weakify(self); basicAnim.completionBlock = ^(POPAnimation *anim, BOOL finished) { @strongify(self); POPPropertyAnimation *basicAnim = (POPPropertyAnimation *)anim; self.progressLayer.strokeEnd = [basicAnim.toValue doubleValue]; if (self.progressLayer.strokeEnd >= 1.0 && _progressFullTintColor) { self.progressLayer.strokeEnd = 1.0; self.progressLayer.strokeColor = _progressFullTintColor.CGColor; } }; [self.progressLayer pop_addAnimation:basicAnim forKey:kPOPShapeLayerStrokeEnd]; } else { self.progressLayer.strokeEnd = progress; if (self.progressLayer.strokeEnd >= 1.0 && _progressFullTintColor) { self.progressLayer.strokeEnd = 1.0; self.progressLayer.strokeColor = _progressFullTintColor.CGColor; } } } @end