From a609d13ff3c5f4b58b286dbb9419fc9670799c99 Mon Sep 17 00:00:00 2001
From: AceSL <1093788164@qq.com>
Date: Sat, 21 Nov 2020 01:08:42 +0000
Subject: [PATCH] first commit

---
 MyCircleView.xcodeproj/xcuserdata/zhangwei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist |    6 +
 MyCircleView/ViewController.m                                                               |   22 +++
 MyCircleView.xcodeproj/project.pbxproj                                                      |    6 +
 MyCircleView/MyCircleView.m                                                                 |  291 +++++++++++++++++++++++++++++++++++++++++++++++-
 MyCircleView/MyCircleView.h                                                                 |    5 
 MyCircleView/AppDelegate.m                                                                  |    1 
 6 files changed, 324 insertions(+), 7 deletions(-)

diff --git a/MyCircleView.xcodeproj/project.pbxproj b/MyCircleView.xcodeproj/project.pbxproj
index 49a9ca7..87803c9 100644
--- a/MyCircleView.xcodeproj/project.pbxproj
+++ b/MyCircleView.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
 		727BE361256754EB00E4C5B9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 727BE360256754EB00E4C5B9 /* main.m */; };
 		727BE36B256754EB00E4C5B9 /* MyCircleViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 727BE36A256754EB00E4C5B9 /* MyCircleViewTests.m */; };
 		727BE376256754EB00E4C5B9 /* MyCircleViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 727BE375256754EB00E4C5B9 /* MyCircleViewUITests.m */; };
+		727BE385256756D700E4C5B9 /* MyCircleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 727BE384256756D700E4C5B9 /* MyCircleView.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -54,6 +55,8 @@
 		727BE371256754EB00E4C5B9 /* MyCircleViewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyCircleViewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		727BE375256754EB00E4C5B9 /* MyCircleViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyCircleViewUITests.m; sourceTree = "<group>"; };
 		727BE377256754EB00E4C5B9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		727BE383256756D700E4C5B9 /* MyCircleView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyCircleView.h; sourceTree = "<group>"; };
+		727BE384256756D700E4C5B9 /* MyCircleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyCircleView.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -110,6 +113,8 @@
 				727BE352256754E800E4C5B9 /* SceneDelegate.m */,
 				727BE354256754E800E4C5B9 /* ViewController.h */,
 				727BE355256754E800E4C5B9 /* ViewController.m */,
+				727BE383256756D700E4C5B9 /* MyCircleView.h */,
+				727BE384256756D700E4C5B9 /* MyCircleView.m */,
 				727BE357256754E800E4C5B9 /* Main.storyboard */,
 				727BE35A256754EB00E4C5B9 /* Assets.xcassets */,
 				727BE35C256754EB00E4C5B9 /* LaunchScreen.storyboard */,
@@ -269,6 +274,7 @@
 			files = (
 				727BE356256754E800E4C5B9 /* ViewController.m in Sources */,
 				727BE350256754E800E4C5B9 /* AppDelegate.m in Sources */,
+				727BE385256756D700E4C5B9 /* MyCircleView.m in Sources */,
 				727BE361256754EB00E4C5B9 /* main.m in Sources */,
 				727BE353256754E800E4C5B9 /* SceneDelegate.m in Sources */,
 			);
diff --git a/MyCircleView.xcodeproj/xcuserdata/zhangwei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MyCircleView.xcodeproj/xcuserdata/zhangwei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
new file mode 100644
index 0000000..0a27701
--- /dev/null
+++ b/MyCircleView.xcodeproj/xcuserdata/zhangwei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   uuid = "E82CAFF4-E0BE-4A60-9854-4E1FB5FAE432"
+   type = "1"
+   version = "2.0">
+</Bucket>
diff --git a/MyCircleView/AppDelegate.m b/MyCircleView/AppDelegate.m
index 40f7a75..57aaa2a 100644
--- a/MyCircleView/AppDelegate.m
+++ b/MyCircleView/AppDelegate.m
@@ -17,6 +17,7 @@
 
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // Override point for customization after application launch.
+    
     return YES;
 }
 
diff --git a/MyCircleView/MyCircleView.h b/MyCircleView/MyCircleView.h
index 649f1a1..bb65283 100644
--- a/MyCircleView/MyCircleView.h
+++ b/MyCircleView/MyCircleView.h
@@ -12,6 +12,11 @@
 
 @interface MyCircleView : UIView
 
+@property (nonatomic, assign) CGFloat strokelineWidth;         //进度条宽度
+
+//progress: 0 ~ 100
+- (void)circleWithProgress:(NSInteger)progress value:(CGFloat)value;
+
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/MyCircleView/MyCircleView.m b/MyCircleView/MyCircleView.m
index 0dde152..ba1fa94 100644
--- a/MyCircleView/MyCircleView.m
+++ b/MyCircleView/MyCircleView.m
@@ -8,14 +8,293 @@
 
 #import "MyCircleView.h"
 
+@interface MyCircleView ()
+
+@property (nonatomic, strong) NSTimer * labelTimer;
+@property (nonatomic, strong) UIView * centerView;
+@property (nonatomic, strong) UILabel * numLabel;
+@property (nonatomic, strong) UILabel * textLabel;
+@property (nonatomic, strong) UILabel * valueLabel;
+
+@property (nonatomic, assign) CGFloat progressFlag;
+@property (nonatomic, assign) NSInteger progressValue;
+
+@property (nonatomic, strong) CAShapeLayer * borderLayer;     //虚线
+@property (nonatomic, strong) CAShapeLayer * backgroundLine;  //进度条背景
+@property (nonatomic, strong) CAShapeLayer * mainLine;        //进度条
+@property (nonatomic, strong) CAShapeLayer * maskLayer;       //遮罩层
+@property (nonatomic, strong) CAGradientLayer * rightGrain;   //渐变layer
+@property (nonatomic, strong) CAGradientLayer * leftGrain;    //渐变layer
+
+@property (nonatomic, strong) CABasicAnimation * pathAnimation;//加载动画
+
+@property (nonatomic, strong) UIBezierPath * borderPath;       //虚线路径
+@property (nonatomic, strong) UIBezierPath * bezierPath;       //进度条路径
+
+@end
+
 @implementation MyCircleView
 
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    if (self) {
+        
+        _strokelineWidth = 6;
+        
+        //外层虚线
+        [self.layer addSublayer:self.borderLayer];
+        self.borderLayer.path = self.borderPath.CGPath;
+        
+        //进度条
+        [self.layer addSublayer:self.backgroundLine];
+        [self.layer addSublayer:self.mainLine];
+        self.backgroundLine.path = self.bezierPath.CGPath;
+        self.mainLine.path = self.bezierPath.CGPath;
+        
+        //添加渐变色
+        [self.layer addSublayer:self.maskLayer];
+        [self.maskLayer addSublayer:self.rightGrain];
+        [self.maskLayer addSublayer:self.leftGrain];
+        [self.maskLayer setMask:self.mainLine];
+        
+        [self addSubview:self.centerView];
+    }
+    
+    return self;
 }
-*/
+
+- (void)circleWithProgress:(NSInteger)progress value:(CGFloat)value
+{
+    _progressFlag = 0;
+    _progressValue = progress;
+
+    //进度条添加动画
+    self.pathAnimation.duration = progress/100.0f;
+    self.pathAnimation.toValue = [NSNumber numberWithFloat:progress/100.f];
+    [self.mainLine addAnimation:self.pathAnimation forKey:@"strokeEndAnimation"];
+
+    //添加文字内容
+    _valueLabel.text = [NSString stringWithFormat:@"%.1fGB/128GB", value];
+
+    if (progress > 0){
+        dispatch_async(dispatch_get_global_queue(0, 0), ^{
+            self->_labelTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(NameLbChange) userInfo:nil repeats:YES];
+            [[NSRunLoop currentRunLoop] run];
+        });
+    }
+}
+
+#pragma mark - timer methods -
+
+- (void)NameLbChange
+{
+    dispatch_async(dispatch_get_main_queue(), ^{
+        self->_numLabel.attributedText = [self labelStytle:self->_progressFlag];
+    });
+    
+    _progressFlag += 1;
+    
+    if (_progressFlag > _progressValue) {
+        [_labelTimer invalidate];
+        _labelTimer = nil;
+    }
+}
+
+- (NSMutableAttributedString *)labelStytle:(NSInteger)value
+{
+    if (value > _progressValue) {
+        value = _progressValue;
+    }
+    
+    NSString * pace = [NSString stringWithFormat:@"%ld%@", value, @"%"];
+    NSMutableAttributedString * pace1 = [[NSMutableAttributedString alloc] initWithString:pace];
+    [pace1 addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:40] range:NSMakeRange(0, pace.length - 1)];
+    [pace1 addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:20] range:NSMakeRange(pace.length - 1, 1)];
+    NSRange titleRange = NSMakeRange(0, pace.length);
+    [pace1 addAttribute:NSForegroundColorAttributeName
+                  value:[UIColor whiteColor]
+                  range:titleRange];
+    return pace1;
+}
+
+
+#pragma mark - lazy -
+
+- (UIView *)centerView
+{
+    if (!_centerView) {
+        _centerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width - _strokelineWidth*2 - 30, self.bounds.size.width - _strokelineWidth*2 - 30)];
+        _centerView.center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
+        _centerView.backgroundColor = [UIColor colorWithRed:85/255.0 green:172/255.0 blue:234/255.0 alpha:1.0];
+        _centerView.layer.masksToBounds = YES;
+        _centerView.layer.cornerRadius = (self.bounds.size.width - _strokelineWidth*2 - 30) / 2;
+        
+        [_centerView addSubview:self.numLabel];
+        [_centerView addSubview:self.textLabel];
+        [_centerView addSubview:self.valueLabel];
+    }
+    
+    return _centerView;
+}
+
+- (UILabel *)valueLabel
+{
+    if (!_valueLabel) {
+        _valueLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, _centerView.bounds.size.height/2 + 40, _centerView.bounds.size.width, 14)];
+        _valueLabel.text = @"40GB/128GB";
+        _valueLabel.textColor = [UIColor whiteColor];
+        _valueLabel.backgroundColor = [UIColor clearColor];
+        _valueLabel.textAlignment = NSTextAlignmentCenter;
+        _valueLabel.font = [UIFont systemFontOfSize:14];
+    }
+    
+    return _valueLabel;
+}
+
+- (UILabel *)textLabel
+{
+    if (!_textLabel) {
+        _textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, _centerView.bounds.size.height/2 - 40 - 12, _centerView.bounds.size.width, 12)];
+        _textLabel.text = @"已使用";
+        _textLabel.textColor = [UIColor whiteColor];
+        _textLabel.backgroundColor = [UIColor clearColor];
+        _textLabel.textAlignment = NSTextAlignmentCenter;
+        _textLabel.font = [UIFont systemFontOfSize:12];
+    }
+    
+    return _textLabel;
+}
+
+- (UILabel *)numLabel
+{
+    if(!_numLabel) {
+        _numLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, _centerView.bounds.size.width, 40)];
+        _numLabel.center = CGPointMake(_centerView.bounds.size.width/2, _centerView.bounds.size.height/2);
+        _numLabel.textAlignment = NSTextAlignmentCenter;
+        _numLabel.backgroundColor = [UIColor clearColor];
+        _numLabel.font = [UIFont boldSystemFontOfSize:40];
+        _numLabel.textColor = [UIColor whiteColor];
+        _numLabel.text = @"0";
+    }
+    
+    return _numLabel;
+}
+
+- (CAShapeLayer *)borderLayer
+{
+    if (!_borderLayer) {
+        _borderLayer = [[CAShapeLayer alloc] init];
+        _borderLayer.fillColor = [UIColor clearColor].CGColor;
+        _borderLayer.strokeColor = [UIColor colorWithRed:85/255.0 green:172/255.0 blue:234/255.0 alpha:1.0].CGColor;
+        _borderLayer.lineWidth = 2.f;
+        _borderLayer.lineCap = @"round";
+        _borderLayer.lineDashPattern = @[@2, @4];
+    }
+    
+    return _borderLayer;
+}
+
+- (CAShapeLayer *)backgroundLine
+{
+    if(!_backgroundLine) {
+        _backgroundLine = [[CAShapeLayer alloc] init];
+        _backgroundLine.fillColor = [UIColor clearColor].CGColor;
+        _backgroundLine.strokeColor = [UIColor colorWithRed:85/255.0 green:172/255.0 blue:234/255.0 alpha:1.0].CGColor;
+        _backgroundLine.lineWidth = _strokelineWidth;
+    }
+    
+    return _backgroundLine;
+}
+
+- (CAShapeLayer *)mainLine
+{
+    if(!_mainLine) {
+        _mainLine = [[CAShapeLayer alloc] init];
+        _mainLine.fillColor = [UIColor clearColor].CGColor;
+        _mainLine.strokeColor = [UIColor whiteColor].CGColor;
+        _mainLine.lineWidth = _strokelineWidth;
+        _mainLine.lineCap = @"round";
+        _mainLine.strokeStart = 0.01;
+    }
+    
+    return _mainLine;
+}
+
+- (CAShapeLayer *)maskLayer
+{
+    if (!_maskLayer) {
+        _maskLayer = [CAShapeLayer layer];
+    }
+    
+    return _maskLayer;
+}
+
+- (CAGradientLayer *)rightGrain
+{
+    if(!_rightGrain) {
+        _rightGrain = [[CAGradientLayer alloc] init];
+        _rightGrain.frame = CGRectMake(self.bounds.size.width/2, 0, self.bounds.size.width/2, self.bounds.size.height);
+        [_rightGrain setColors:[NSArray arrayWithObjects:
+                           (id)[[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0] CGColor],
+                           (id)[[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0] CGColor],
+                           nil]];
+        [_rightGrain setLocations:@[@0, @1.0]];
+        [_rightGrain setStartPoint:CGPointMake(0.5, 0)];
+        [_rightGrain setEndPoint:CGPointMake(0.5, 1)];
+        _rightGrain.type = kCAGradientLayerAxial;
+    }
+    
+    return _rightGrain;
+}
+
+- (CAGradientLayer *)leftGrain
+{
+    if (!_leftGrain) {
+        _leftGrain = [[CAGradientLayer alloc] init];
+        _leftGrain.frame = CGRectMake(0, 0, self.bounds.size.width/2, self.bounds.size.height);
+        [_leftGrain setColors:[NSArray arrayWithObjects:
+                           (id)[[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0] CGColor],
+                           (id)[[UIColor colorWithRed:255/255.0 green:0/255.0 blue:0/255.0 alpha:1.0] CGColor],
+                           nil]];
+        [_leftGrain setLocations:@[@0.5, @1.0]];
+        [_leftGrain setStartPoint:CGPointMake(0.5, 1)];
+        [_leftGrain setEndPoint:CGPointMake(0.5, 0)];
+        _leftGrain.type = kCAGradientLayerAxial;
+    }
+    
+    return _leftGrain;
+}
+
+- (CABasicAnimation *)pathAnimation
+{
+    if (!_pathAnimation) {
+        _pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        _pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+        _pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
+        _pathAnimation.fillMode = kCAFillModeForwards;
+        _pathAnimation.removedOnCompletion = NO;
+    }
+    
+    return _pathAnimation;
+}
+
+- (UIBezierPath *)borderPath
+{
+    if (!_borderPath) {
+        _borderPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.width/2) radius:self.bounds.size.width/2 startAngle:-M_PI_2 endAngle:-M_PI_2 + M_PI*2 clockwise:YES];
+    }
+    
+    return _borderPath;
+}
+
+- (UIBezierPath *)bezierPath
+{
+    if (!_bezierPath) {
+        _bezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:self.bounds.size.width/2 - _strokelineWidth - 4 startAngle:-M_PI_2 endAngle:-M_PI_2 + M_PI*2 clockwise:YES];
+    }
+    
+    return _bezierPath;
+}
 
 @end
diff --git a/MyCircleView/ViewController.m b/MyCircleView/ViewController.m
index 20e11df..b8627b9 100644
--- a/MyCircleView/ViewController.m
+++ b/MyCircleView/ViewController.m
@@ -7,9 +7,10 @@
 //
 
 #import "ViewController.h"
+#import "MyCircleView.h"
 
 @interface ViewController ()
-
+@property (nonatomic,strong) MyCircleView *circleV;
 @end
 
 @implementation ViewController
@@ -17,6 +18,25 @@
 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
+    
+    self.view.backgroundColor = [UIColor colorWithRed:41/255.0 green:133/255.0 blue:266/255.0 alpha:1.0];
+    
+    _circleV = [[MyCircleView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
+    [self.view addSubview:_circleV];
+    [_circleV circleWithProgress:90 value:128 * 0.9];
+    
+    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
+    button.frame = CGRectMake(100, 400, 100, 44);
+    [button setTitle:@"刷新" forState:UIControlStateNormal];
+    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
+    [self.view addSubview:button];
+    [button addTarget:self action:@selector(refreshAnimation) forControlEvents:UIControlEventTouchUpInside];
+}
+
+- (void)refreshAnimation
+{
+    NSInteger progress = arc4random_uniform(100);
+    [_circleV circleWithProgress:progress value:128 * progress/100.0];
 }
 
 

--
Gitblit v1.9.1