#import <UIKit/UIKit.h> @interface HWCircleView : UIView @property (nonatomic, assign) CGFloat progress; //进度条颜色 @property(nonatomic,strong) UIColor *progerssColor; //进度条背景颜色 @property(nonatomic,strong) UIColor *progerssBackgroundColor; //进度条的宽度 @property(nonatomic,assign) CGFloat progerWidth; //进度数据字体大小 @property(nonatomic,assign)CGFloat percentageFontSize; //进度数字颜色 @property(nonatomic,strong) UIColor *percentFontColor; @end
#import "HWCircleView.h" @interface HWCircleView () @property (nonatomic, weak) UILabel *cLabel; @end @implementation HWCircleView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor clearColor]; //默认颜色 self.progerssBackgroundColor=[UIColor lightGrayColor]; self.progerssColor=[UIColor blueColor]; self.percentFontColor=[UIColor blueColor]; //默认进度条宽度 self.progerWidth=15; //默认百分比字体大小 self.percentageFontSize=22; //百分比标签 UILabel *cLabel = [[UILabel alloc] initWithFrame:self.bounds]; cLabel.font = [UIFont boldSystemFontOfSize:self.percentageFontSize]; cLabel.textColor = self.percentFontColor; cLabel.textAlignment = NSTextAlignmentCenter; [self addSubview:cLabel]; self.cLabel = cLabel; } return self; } - (void)setProgress:(CGFloat)progress { _progress = progress; _cLabel.text = [NSString stringWithFormat:@"%d%%", (int)floor(progress * 100)]; [self setNeedsDisplay]; } - (void)drawRect:(CGRect)rect { //路径 UIBezierPath *backgroundPath = [[UIBezierPath alloc] init]; //线宽 backgroundPath.lineWidth = self.progerWidth; //颜色 [self.progerssBackgroundColor set]; //拐角 backgroundPath.lineCapStyle = kCGLineCapRound; backgroundPath.lineJoinStyle = kCGLineJoinRound; //半径 CGFloat radius = (MIN(rect.size.width, rect.size.height) - self.progerWidth) * 0.5; //画弧(参数:中心、半径、起始角度(3点钟方向为0)、结束角度、是否顺时针) [backgroundPath addArcWithCenter:(CGPoint){rect.size.width * 0.5, rect.size.height * 0.5} radius:radius startAngle:M_PI * 1.5 endAngle:M_PI * 1.5 + M_PI * 2 clockwise:YES]; //连线 [backgroundPath stroke]; //路径 UIBezierPath *progressPath = [[UIBezierPath alloc] init]; //线宽 progressPath.lineWidth = self.progerWidth; //颜色 [self.progerssColor set]; //拐角 progressPath.lineCapStyle = kCGLineCapRound; progressPath.lineJoinStyle = kCGLineJoinRound; //画弧(参数:中心、半径、起始角度(3点钟方向为0)、结束角度、是否顺时针) [progressPath addArcWithCenter:(CGPoint){rect.size.width * 0.5, rect.size.height * 0.5} radius:radius startAngle:M_PI * 1.5 endAngle:M_PI * 1.5 + M_PI * 2 * _progress clockwise:YES]; //连线 [progressPath stroke]; } @end
@property (nonatomic, strong) NSTimer *timer; @property (nonatomic, weak) HWCircleView *circleView; - (void)viewDidLoad { [super viewDidLoad]; //建立控件 HWCircleView *circleView = [[HWCircleView alloc] initWithFrame:CGRectMake(50, 200, 150, 150)]; [self.view addSubview:circleView]; self.circleView = circleView;; //添加定时器 [self addTimer]; } - (void)addTimer { //建立定时器 _timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(timerAction) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; } - (void)timerAction { _circleView.progress += 0.01; if (_circleView.progress >= 1) { [self removeTimer]; NSLog(@"完成"); } } - (void)removeTimer { [_timer invalidate]; _timer = nil; }
<hr>异步
######UIView的setNeedsDisplay和setNeedsLayout方法oop
首先两个方法都是异步执行的。而setNeedsDisplay会调用自动调用drawRect方法进行绘制功能,这样能够拿到 UIGraphicsGetCurrentContext,就能够进行绘制了。而setNeedsLayout会默认调用layoutSubViews, 就能够 处理子视图中的一些数据。 综上所诉,setNeedsDisplay方便绘图,而layoutSubViews方便出来数据。字体
<hr>atom
一、init初始化不会触发layoutSubviews。 二、addSubview会触发layoutSubviews。 三、设置view的Frame会触发layoutSubviews,固然前提是frame的值设置先后发生了变化。 四、滚动一个UIScrollView会触发layoutSubviews。 五、旋转Screen会触发父UIView上的layoutSubviews事件。 六、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。 七、直接调用setLayoutSubviews。code
<hr>orm
######drawRect在如下状况下会被调用:blog
一、若是在UIView初始化时没有设置rect大小,将直接致使drawRect不被自动调用。drawRect调用是在Controller->loadView, Controller->viewDidLoad 两方法以后掉用的.因此不用担忧在控制器中,这些View的drawRect就开始画了.这样能够在控制器中设置一些值给View(若是这些View draw的时候须要用到某些变量值).事件
二、该方法在调用sizeToFit后被调用,因此能够先调用sizeToFit计算出size。而后系统自动调用drawRect:方法。图片
三、经过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。ci
四、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,可是有个前提条件是rect不能为0。 以上1,2推荐;而3,4不提倡
<hr>
######drawRect方法使用注意点:
一、若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。若是在其余方法中获取将获取到一个invalidate的ref而且不能用于画图。drawRect:方法不能手动显示调用,必须经过调用setNeedsDisplay 或者 setNeedsDisplayInRect,让系统自动调该方法。 二、若使用CAlayer绘图,只能在drawInContext: 中(相似于drawRect)绘制,或者在delegate中的相应方法绘制。一样也是调用setNeedDisplay等间接调用以上方法 三、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕