iOS 进度条

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
    

    效果:
    像瓶子一样的,哈哈哈.....

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值