绘制扇形进度条
背景:上传文件的时候,需要有上传进度,这次需要一个扇形的进度条,示例图如下:
![](https://img.haomeiwen.com/i14043261/8a522fabf8edb54a.jpg)
废话不多说,上代码:
/**
扇形图进度条
角度:可选择起始角度:SLSectorStartAngle:top left bottom and right
旋转:顺时针旋转
半径:radius
填充色:fillColor
*/
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, SLSectorStartAngle) {
SLSectorStartAngle_top = 0,
SLSectorStartAngle_left,
SLSectorStartAngle_bottom,
SLSectorStartAngle_right,
};
@interface SLSectorProgressBar : UIView
/// 构造方法
/// @param startAngle 初始角度
- (instancetype)initWithStartAngle:(SLSectorStartAngle)startAngle radius:(CGFloat)radius fillColor:(UIColor *)fillColor;
/// 进度
@property(nonatomic, assign) CGFloat progress;
/// 配置边框颜色和宽度
/// @param borderColor 边框颜色
/// @param borderWidth 边框宽度
- (void)configBorderWithColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;
/// 没有进度时,是否需要占位线(如果需要下面的绘制外圈的圆圈,一般都需要绘制默认占位线)
@property (nonatomic, assign) BOOL needPlaceholderLine;
@end
#import "SLSectorProgressBar.h"
@interface SLSectorProgressBar ()
/// 开始角度
@property (nonatomic, assign) SLSectorStartAngle startAngle;
/// 半径
@property (nonatomic, assign) CGFloat radius;
/// 填充色
@property (nonatomic, strong) UIColor *fillColor;
/// 边框颜色
@property (nonatomic, strong) UIColor *borderColor;
/// 边框粗细
@property (nonatomic, assign) CGFloat borderWidth;
@end
@implementation SLSectorProgressBar
- (instancetype)initWithStartAngle:(SLSectorStartAngle)startAngle radius:(CGFloat)radius fillColor:(UIColor *)fillColor {
if (self = [super init]) {
self.backgroundColor = [UIColor clearColor];
_startAngle = startAngle;
_radius = radius ?: 200;
_fillColor = fillColor ?: [UIColor cyanColor];
}
return self;
}
- (void)configBorderWithColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
_borderColor = borderColor;
_borderWidth = borderWidth;
}
#pragma mark - 更新进度
- (void)setProgress:(CGFloat)progress{
_progress = progress;
[self setNeedsDisplay];
}
#pragma mark - 绘制图形
- (void)drawRect:(CGRect)rect {
[self drawLine];
[self drawProgress];
}
// 绘制外圈线条
- (void)drawLine {
CGPoint origin = CGPointMake(_radius/2, _radius/2);
CGFloat radius = _radius/2 - _borderWidth/2;
CGFloat startAngle = 0;
CGFloat endAngle = 2*M_PI;
UIBezierPath *sectorPath = [UIBezierPath bezierPathWithArcCenter:origin radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
if (self.needPlaceholderLine) {
[sectorPath moveToPoint:origin];
[sectorPath addLineToPoint:CGPointMake(_radius/2, 0)];
}
sectorPath.lineWidth = _borderWidth;
[_borderColor set];
[sectorPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
// 绘制进度条
- (void)drawProgress {
// 中心点
CGPoint origin = CGPointMake(_radius/2, _radius/2);
// 半径
CGFloat radius = _radius/2;
// 起始角度
CGFloat startAngle = [self fetchStartAngle];
// 结束角度
CGFloat endAngle = [self fetchEndAngle];
// 开始绘制
UIBezierPath *sectorPath = [UIBezierPath bezierPathWithArcCenter:origin radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
[sectorPath addLineToPoint:origin];
[_fillColor set];
[sectorPath fill];
}
#pragma mark - Tools
- (CGFloat)fetchStartAngle {
CGFloat angle = - M_PI_2; // 默认top
switch (_startAngle) {
case SLSectorStartAngle_left:
angle = M_PI;
break;
case SLSectorStartAngle_bottom:
angle = M_PI_2;
break;
case SLSectorStartAngle_right:
angle = M_PI * 2;
break;
default:
break;
}
return angle;
}
- (CGFloat)fetchEndAngle {
CGFloat angle = [self fetchStartAngle] + self.progress * M_PI * 2;
return angle;
}
@end
以上代码的调用方式如下:
#import "ViewController.h"
#import "SLSectorProgressBar.h"
@interface ViewController ()
@property (nonatomic, strong) UISlider *slider;
@property (nonatomic, strong) SLSectorProgressBar *sectorView;
@property (nonatomic, strong) UIColor *testColor;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.testColor = [UIColor redColor];
[self.view addSubview:self.slider];
[self.view addSubview:self.sectorView];
}
- (void)sliderValueChange:(UISlider *)sender {
self.sectorView.progress = (sender.value - sender.minimumValue) / (sender.maximumValue - sender.minimumValue);
}
- (UISlider *)slider {
if (_slider == nil) {
_slider = [[UISlider alloc] initWithFrame:CGRectMake(50, 100, self.view.frame.size.width - 100, 50)];
[_slider addTarget:self action:@selector(sliderValueChange:) forControlEvents:UIControlEventValueChanged];
[_slider setMinimumTrackTintColor:self.testColor];
}
return _slider;
}
- (SLSectorProgressBar *)sectorView {
if (_sectorView == nil) {
_sectorView = [[SLSectorProgressBar alloc] initWithStartAngle:SLSectorStartAngle_top radius:200 fillColor: self.testColor];
[_sectorView configBorderWithColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.1] borderWidth:3];
_sectorView.progress = 0;
CGFloat wh = 200;
CGFloat y = CGRectGetMaxY(self.slider.frame) + 10;
CGFloat x = (self.view.frame.size.width - wh) / 2;
_sectorView.frame = CGRectMake(x, y, wh, wh);
}
return _sectorView;
}
@end
按照上面代码跑起来,示例图如下:
![](https://img.haomeiwen.com/i14043261/2bb587c848a95a12.jpg)
网友评论