iOS开发中,我们经常使用进度条,首先我们会经常使用UIProgressView,系统的这个进度条高度不能定制,可设置背景颜色及跟踪颜色!有时候无法满足我们UI设计师的个人偏好(╯︵╰).我们来自定义几种进度条以在开发中满足他们的愿望!
WMProgressView.h文件
#import
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
WMPieChartProgressView.h
#import
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
WMRingProgressView.h
#import
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
使用UIBezierPath画出路径(形似瓶子,勿喷…)
WMBottleWaveView.h
#import
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