iOS开发中,我们经常使用进度条,首先我们会经常使用UIProgressView,系统的这个进度条高度不能定制,可设置背景颜色及跟踪颜色!有时候无法满足我们UI设计师的个人偏好(╯︵╰).我们来自定义几种进度条以在开发中满足他们的愿望!
1.条形进度条
-
WMProgressView.h文件
#import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface WMProgressView : UIView @property (nonatomic ,assign) CGFloat progress; /** * 创建对象方法 * * @param frame WMProgressView的frame * @param bgViewBgColor WMProgressView的背景色 * @param bgViewBorderColor WMProgressView的Border颜色 * @param progressViewColor 进度条的颜色 * * @return 进度条view */ - (instancetype)initWithFrame:(CGRect)frame BgViewBgColor:(UIColor *)bgViewBgColor BgViewBorderColor:(UIColor *)bgViewBorderColor ProgressViewColor:(UIColor *)progressViewColor; @end NS_ASSUME_NONNULL_END
-
WMProgressView.m文件
#import "WMProgressView.h" @interface WMProgressView () @property (nonatomic, strong) UIView *progressView; @end @implementation WMProgressView - (instancetype)initWithFrame:(CGRect)frame BgViewBgColor:(UIColor *)bgViewBgColor BgViewBorderColor:(UIColor *)bgViewBorderColor ProgressViewColor:(UIColor *)progressViewColor { if (self = [super initWithFrame:frame]) { self.layer.cornerRadius = self.bounds.size.height * 0.5; self.layer.masksToBounds = YES; self.backgroundColor = bgViewBgColor; self.layer.borderColor = bgViewBorderColor.CGColor; self.layer.borderWidth = 1; //进度 self.progressView = [[UIView alloc] init]; self.progressView.backgroundColor = progressViewColor; self.progressView.layer.cornerRadius = (self.bounds.size.height - 2) * 0.5; self.progressView.layer.masksToBounds = YES; [self addSubview:self.progressView]; } return self; } - (void)setProgress:(CGFloat)progress { _progress = progress; CGFloat width = self.bounds.size.width - 2; CGFloat heigth = self.bounds.size.height - 2; _progressView.frame = CGRectMake(1, 1, width * progress, heigth); } @end
使用时直接使用对象方法创建对象,当progress改变时,设置progress即可!效果:
2.扇形图
-
WMPieChartProgressView.h
#import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface WMPieChartProgressView : UIView @property (nonatomic, assign) CGFloat progress; @end NS_ASSUME_NONNULL_END
-
WMPieChartProgressView.m
#import "WMPieChartProgressView.h" @implementation WMPieChartProgressView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor clearColor]; } return self; } - (void)setProgress:(CGFloat)progress { _progress = progress; [self setNeedsDisplay]; } - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGFloat CenterX = rect.size.width * 0.5;//中心点X CGFloat CenterY = rect.size.height * 0.5;//中心点Y CGFloat radius = MIN(rect.size.width, rect.size.height) * 0.5 - 10; //背景 [[UIColor orangeColor] set]; CGFloat lineW = MAX(rect.size.width, rect.size.height) * 0.5; CGContextSetLineWidth(context, lineW); CGContextAddArc(context, CenterX, CenterY, radius + lineW * 0.5 + 5, 0, M_PI * 2, 1); CGContextStrokePath(context); //进度圆 CGContextSetLineWidth(context, 1); CGContextMoveToPoint(context, CenterX, CenterY); CGContextAddLineToPoint(context, CenterX, 0); CGFloat endAngle = - M_PI * 0.5 + _progress * M_PI * 2 + 0.001; CGContextAddArc(context, CenterX, CenterY, radius, - M_PI * 0.5, endAngle, 1); CGContextFillPath(context); } @end
直接创建,设置frame,progress改变时设置progress即可.效果:
3.圆环
-
WMRingProgressView.h
#import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface WMRingProgressView : UIView @property (nonatomic, assign) CGFloat progress; @end NS_ASSUME_NONNULL_END
-
WMRingProgressView.m
#import "WMRingProgressView.h" @interface WMRingProgressView () @property (nonatomic, strong) UILabel *percentage; @end @implementation WMRingProgressView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupUI]; } return self; } - (void)setupUI { self.backgroundColor = [UIColor clearColor]; //百分比标签 UILabel *percentage = [[UILabel alloc] initWithFrame:self.bounds]; percentage.font = [UIFont boldSystemFontOfSize:20.0f]; percentage.textColor = [UIColor orangeColor]; percentage.textAlignment = NSTextAlignmentCenter; [self addSubview:percentage]; self.percentage = percentage; } - (void)setProgress:(CGFloat)progress { _progress = progress; _percentage.text = [NSString stringWithFormat:@"%d%%", (int)floor(progress * 100)]; [self setNeedsDisplay]; } - (void)drawRect:(CGRect)rect { UIBezierPath *ringPath = [[UIBezierPath alloc] init];//圆环路径 ringPath.lineWidth = 5.0;//圆环宽度 [[UIColor orangeColor] set];//环的颜色 ringPath.lineCapStyle = kCGLineCapRound; ringPath.lineJoinStyle = kCGLineJoinRound; //半径 取view小的一边做半径 CGFloat radius = (MIN(rect.size.width, rect.size.height) - 5.0) * 0.5; /* 画弧 Center:圆环中心点 radius:圆环半径 startAngle:开始角度(三点钟那个方向是0度) -M_PI*0.5 12点钟方向 endAngle:结束的角度 -M_PI*0.5 在此基础上加到 2*M_PI clockwise:YES顺时针 NO逆时针 */ [ringPath addArcWithCenter:CGPointMake(rect.size.width*0.5, rect.size.height*0.5) radius:radius startAngle:-M_PI*0.5 endAngle:-M_PI*0.5 + M_PI*2*_progress clockwise:YES]; //填充模式 [ringPath stroke]; } @end
效果:
4.波浪形的(随便写的)
使用UIBezierPath画出路径(形似瓶子,勿喷…)
-
WMBottleWaveView.h
#import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN @interface WMBottleWaveView : UIView @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic, assign) CGFloat wave_amplitude;//振幅a(y = asin(wx+φ) + k) @property (nonatomic, assign) CGFloat wave_cycle;//周期w @property (nonatomic, assign) CGFloat wave_rate;//水波速率 @property (nonatomic, assign) CGFloat wave_offsetY;//波峰所在位置的y坐标 @property (nonatomic, assign) CGFloat wave_m_distance;//移动的距离,配合速率设置 @property (nonatomic, assign) CGFloat wave_offsetX;//偏移 @property (nonatomic, assign) CGFloat offsetY_rate;//上升的速度 @property (nonatomic, assign) CGFloat progress; @end NS_ASSUME_NONNULL_END
-
WMBottleWaveView.m
#import "WMBottleWaveView.h" @implementation WMBottleWaveView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor clearColor]; //初始化信息 [self initData]; } return self; } - (void)initData { //进度 _progress = 0; //振幅 _wave_amplitude = self.frame.size.height / 50; //周期 _wave_cycle = M_PI / (self.frame.size.width * 0.8); //移动的距离,配合速率设置 _wave_m_distance = 0.5; //水波速率 _wave_rate = 0.4; //上升的速度 _offsetY_rate = 0.1; //波峰所在位置的y坐标,刚开始的时候_wave_offsetY是最大值 _wave_offsetY = (1 - _progress) * (self.frame.size.height + 2 * _wave_amplitude); [self addDisplayLinkAction]; } //定时器 - (void)addDisplayLinkAction { _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkAction)]; [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } - (void)displayLinkAction { _wave_offsetX += _wave_m_distance * _wave_rate; if (_wave_offsetY <= 0.01) { //完成后释放定时器 [self removeDisplayLinkAction]; } [self setNeedsDisplay]; } //释放定时器 - (void)removeDisplayLinkAction { [_displayLink invalidate]; _displayLink = nil; } - (void)drawRect:(CGRect)rect { //设置容器线条颜色 UIColor *color = [UIColor orangeColor]; [color set]; //创建UIBezierPath UIBezierPath *apath = ({ UIBezierPath *path = [UIBezierPath bezierPath]; path.lineWidth = 5.0f; //设置线条宽度 path.lineCapStyle = kCGLineCapRound; //设置拐角 path.lineJoinStyle = kCGLineCapRound; //终点处理 //设置起始点 [path moveToPoint:CGPointMake(40, 0)]; [path addLineToPoint:CGPointMake(40, 40)]; [path addArcWithCenter:CGPointMake(0, 40) radius:40 startAngle:0 endAngle:M_PI/2 clockwise:YES]; //增加线条 [path addLineToPoint:CGPointMake(0, self.frame.size.height)]; [path addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height)]; [path addLineToPoint:CGPointMake(self.frame.size.width, 80)]; [path addArcWithCenter:CGPointMake(self.frame.size.width, 40) radius:40 startAngle:M_PI_2 endAngle:M_PI clockwise:YES]; [path addLineToPoint:CGPointMake(self.frame.size.width-40, 0)]; //关闭路径 [path closePath]; [path addClip]; path; }); //根据坐标连线 [apath stroke]; //绘制波形图 [self drawWaveColor:[UIColor orangeColor]]; } //画波浪线 - (void)drawWaveColor:(UIColor *)color { CGFloat end_offY = (1 - _progress) * (self.frame.size.height + 2 * _wave_amplitude); if (_wave_offsetY != end_offY) { if (end_offY < _wave_offsetY) { _wave_offsetY = MAX(_wave_offsetY -= (_wave_offsetY - end_offY) * _offsetY_rate, end_offY); } else { _wave_offsetY = MIN(_wave_offsetY += (end_offY - _wave_offsetY) * _offsetY_rate, end_offY); } } UIBezierPath *wavePath = [UIBezierPath bezierPath]; for (float next_x = 0.f; next_x <= self.frame.size.width; next_x ++) { //正弦函数,绘制波形 CGFloat next_y = _wave_amplitude * sin(_wave_cycle * next_x + _wave_offsetX) + _wave_offsetY; if (next_x == 0) { [wavePath moveToPoint:CGPointMake(next_x, next_y - _wave_amplitude)]; } else { [wavePath addLineToPoint:CGPointMake(next_x, next_y - _wave_amplitude)]; } } [wavePath addLineToPoint:CGPointMake(self.frame.size.width, self.frame.size.height)]; [wavePath addLineToPoint:CGPointMake(0, self.bounds.size.height)]; [color set]; //填充 [wavePath fill]; } @end
效果: