欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

渐变、虚线、圆形进度条

程序员文章站 2022-03-15 10:26:09
主要用到CAShapeLayer,CAGradientLayer 结合实现圆形进度条可设置是否是虚线可设置起始角度可设置进度条方向可设置进度条线宽可设置虚线的长度可设置背景圆环颜色可设置背景进度条的闭合样式可设置是否显示背景圆环 /// 渐变色 layer@property (nonatomic, strong) CAGradientLayer *progressGradientLayer;/// 底色 layer@property (nonatomic, strong) CA....

主要用到CAShapeLayer,CAGradientLayer 结合实现圆形进度条

  • 可设置是否是虚线
  • 可设置起始角度
  • 可设置进度条方向
  • 可设置进度条线宽
  • 可设置虚线的长度
  • 可设置背景圆环颜色
  • 可设置背景进度条的闭合样式
  • 可设置是否显示背景圆环
 /// 渐变色 layer
@property (nonatomic, strong) CAGradientLayer *progressGradientLayer;
/// 底色 layer
@property (nonatomic, strong) CAShapeLayer *bottomLayer;
/// 进度遮罩layer   加在渐变 层上的mask
@property (nonatomic, strong) CAShapeLayer *progressLayer;

通过设置progressLayer的Path改变进度

主要代码

- RoundProgressView.h

/**
 * 圆形进度条
 * - 可设置是否是虚线
 * - 可设置起始角度
 * - 可设置进度条方向
 * - 可设置进度条线宽
 * - 可设置虚线的长度
 * - 可设置背景圆环颜色
 * - 可设置背景进度条的闭合样式
 * - 可设置是否显示背景圆环
 */
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface RoundProgressView : UIView

/// 起始角度
@property (nonatomic, assign) CGFloat  startAngle;
/// 是否是顺时针
@property (nonatomic, assign) BOOL  isClockwise;
/// 0-1.0
@property (nonatomic, assign) CGFloat  progress;
/// 线宽
@property (nonatomic, assign) CGFloat  lineWidth;
/// 是否以虚线形式展示注意线段间隔太短时会受到lineCap影响可能看不到效果
@property (nonatomic, assign) BOOL  shouldWithDashPattern;
///虚线长度设置
@property (nonatomic, strong) NSArray *dashPattern;
///背景圆环颜色
@property (nonatomic, strong) UIColor *maxTintColor;
///进度条的渐变色
@property (nonatomic, copy) NSArray *progressColors;
///进度条闭合方式
@property (nonatomic, copy) CAShapeLayerLineCap lineCap;
///是否显示底部圆环
@property (nonatomic, assign) BOOL  showBottomProgress;

/// 设置进度条渐变色的相关属性
/// @param handle 回调
- (void)setProgressGradientLayerHandle:(void(^)(CAGradientLayer *gradientLayer))handle;

/// 设置进度条线宽虚线进度等相关属性
/// @param handle 回调
- (void)setProgressLayerHandle:(void(^)(CAShapeLayer *progressLayer))handle;

/// 设置底部圆环相关属性
/// @param handle 回调
- (void)setBottomLayerHandle:(void(^)(CAShapeLayer *bottomLayer))handle;
@end

NS_ASSUME_NONNULL_END

- RoundProgressView.m

#import "RoundProgressView.h"
#define kSelfWidth self.frame.size.width
#define kSelfHeight self.frame.size.height
@interface RoundProgressView()
@property (nonatomic, strong) UILabel *inforLabel;
/// 渐变色 layer
@property (nonatomic, strong) CAGradientLayer *progressGradientLayer;
/// 底色 layer
@property (nonatomic, strong) CAShapeLayer *bottomLayer;
/// 进度遮罩layer   加在渐变 层上的mask
@property (nonatomic, strong) CAShapeLayer *progressLayer;
@end

@implementation RoundProgressView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _startAngle = 0;
        _isClockwise = YES;
        _lineWidth = 4;
        _shouldWithDashPattern = NO;
        _dashPattern = @[@(2),@(2)];
        _lineCap = kCALineCapRound;
        _maxTintColor = [UIColor grayColor];
        _startAngle = 0;
        _showBottomProgress = YES;
        _progressColors = @[(id)UIColor.orangeColor.CGColor,(id)UIColor.redColor.CGColor];
        [self.layer addSublayer:self.bottomLayer];
        [self.layer addSublayer:self.progressGradientLayer];
        [self addSubview:self.inforLabel];
        
    }
    return self;
}
- (void)layoutSubviews {
    [super layoutSubviews];
    self.bottomLayer.frame = self.bounds;
    self.progressLayer.frame = self.bounds;
    self.progressGradientLayer.frame = self.bounds;
    [self p_drawBottom];
    _inforLabel.frame = self.bounds;
}

/// 重绘
- (void)redrawProgress {
    [self p_drawBottom];
    [self p_drawProgress];
}

/// 绘制进度mask
- (void)p_drawProgress {
    CGPoint center = CGPointMake(kSelfWidth/2.0, kSelfHeight/2.0);
    CGFloat radius = kSelfWidth/2.0-_lineWidth/2.0;
    CGFloat endAngle = M_PI * 2 *_progress + _startAngle;
    if (!_isClockwise) {
        endAngle = _startAngle - M_PI * 2 *_progress;
    }
    self.progressLayer.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:_startAngle endAngle:endAngle clockwise:_isClockwise].CGPath;
}

/// 绘制底色layer
- (void)p_drawBottom {
    CGPoint center = CGPointMake(kSelfWidth/2.0, kSelfHeight/2.0);
    CGFloat radius = kSelfWidth/2.0-_lineWidth/2.0;
    CGFloat endAngle = M_PI * 2 + _startAngle;
    if (!_isClockwise) {
        endAngle = _startAngle - M_PI * 2;
    }
    self.bottomLayer.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:_startAngle endAngle:endAngle clockwise:_isClockwise].CGPath;
}


#pragma mark - Public Methods
- (void)setProgressGradientLayerHandle:(void (^)(CAGradientLayer * _Nonnull))handle {
    if (handle) {
        handle(self.progressGradientLayer);
    }
}
- (void)setProgressLayerHandle:(void (^)(CAShapeLayer * _Nonnull))handle {
    if (handle) {
        handle(self.progressLayer);
        [self p_drawProgress];
    }
}
- (void)setBottomLayerHandle:(void (^)(CAShapeLayer * _Nonnull))handle {
    if (handle) {
        handle(self.bottomLayer);
        [self p_drawBottom];
    }
}
#pragma mark - setterMethods
- (void)setProgressColors:(NSArray *)progressColors {
    _progressColors = progressColors.copy;
    self.progressGradientLayer.colors = progressColors;
}
- (void)setLineWidth:(CGFloat)lineWidth {
    _lineWidth = lineWidth;
    self.bottomLayer.lineWidth = _lineWidth;
    self.progressLayer.lineWidth = _lineWidth;
    [self redrawProgress];
}
- (void)setProgress:(CGFloat)progress {
    _progress = progress;
    self.inforLabel.text = [NSString stringWithFormat:@"%ld%%",(NSInteger)(_progress*100)%101];
    [self p_drawProgress];
}
- (void)setShouldWithDashPattern:(BOOL)shouldWithDashPattern {
    _shouldWithDashPattern = shouldWithDashPattern;
    if (_shouldWithDashPattern && _dashPattern.count) {
        self.progressLayer.lineDashPattern = _dashPattern;
        self.bottomLayer.lineDashPattern = _dashPattern;
    } else {
        self.progressLayer.lineDashPattern = nil;
        self.bottomLayer.lineDashPattern = nil;
    }
    [self redrawProgress];
}
- (void)setDashPattern:(NSArray *)dashPattern {
    _dashPattern = [dashPattern copy];
    if (_shouldWithDashPattern && _dashPattern.count) {
        self.progressLayer.lineDashPattern = _dashPattern;
        self.bottomLayer.lineDashPattern = _dashPattern;
    } else {
        self.progressLayer.lineDashPattern = nil;
        self.bottomLayer.lineDashPattern = nil;
    }
    [self redrawProgress];
}
- (void)setLineCap:(CAShapeLayerLineCap)lineCap {
    _lineCap = [lineCap copy];
    self.progressLayer.lineCap = _lineCap;
    self.bottomLayer.lineCap = _lineCap;
    [self redrawProgress];
}
- (void)setMaxTintColor:(UIColor *)maxTintColor {
    _maxTintColor = maxTintColor;
    self.bottomLayer.strokeColor = _maxTintColor.CGColor;
    [self p_drawBottom];
}
- (void)setStartAngle:(CGFloat)startAngle {
    _startAngle = startAngle;
    [self redrawProgress];
}
- (void)setIsClockwise:(BOOL)isClockwise {
    _isClockwise = isClockwise;
    [self redrawProgress];
}
- (void)setShowBottomProgress:(BOOL)showBottomProgress {
    _showBottomProgress = showBottomProgress;
    self.bottomLayer.hidden = !_showBottomProgress;
}
#pragma mark - getterMethods
- (CAShapeLayer *)bottomLayer {
    if (!_bottomLayer) {
        _bottomLayer = [CAShapeLayer layer];
        _bottomLayer.lineWidth = _lineWidth;
        _bottomLayer.lineCap = _lineCap;
        _bottomLayer.strokeStart = 0;
        _bottomLayer.strokeEnd = 1;
        _bottomLayer.fillColor = [UIColor clearColor].CGColor;
        _bottomLayer.strokeColor = _maxTintColor.CGColor;
        _bottomLayer.hidden = !_showBottomProgress;
    }
    return _bottomLayer;
}
- (CAGradientLayer *)progressGradientLayer {
    if (!_progressGradientLayer) {
        _progressGradientLayer = [CAGradientLayer layer];
        _progressGradientLayer.startPoint = CGPointZero;
        _progressGradientLayer.endPoint = CGPointMake(1, 1);
        _progressGradientLayer.locations = @[@(0),@(1)];
        _progressGradientLayer.colors = _progressColors;
        self.progressGradientLayer.mask=  self.progressLayer;
    }
    return _progressGradientLayer;
}
- (CAShapeLayer *)progressLayer {
    if (!_progressLayer) {
        _progressLayer = [CAShapeLayer layer];
        _progressLayer.lineWidth = _lineWidth;
        _progressLayer.lineCap = _lineCap;
        _progressLayer.strokeStart = 0;
        _progressLayer.strokeEnd = 1;
        _progressLayer.strokeColor = UIColor.greenColor.CGColor;
        _progressLayer.fillColor = UIColor.clearColor.CGColor;
    }
    return _progressLayer;
}
- (UILabel *)inforLabel {
    if (!_inforLabel) {
        _inforLabel = [[UILabel alloc] init];
        _inforLabel.textColor = [UIColor redColor];
        _inforLabel.font = [UIFont systemFontOfSize:20];
        _inforLabel.numberOfLines = 0;
        _inforLabel.text = [NSString stringWithFormat:@"%ld%%",(NSInteger)(_progress*100)%101];
        _inforLabel.textAlignment = NSTextAlignmentCenter;
    }
    return _inforLabel;
}
@end

效果展示

渐变、虚线、圆形进度条
渐变、虚线、圆形进度条
渐变、虚线、圆形进度条

源码:

CircleProgressDemo

本文地址:https://blog.csdn.net/u013227512/article/details/108870001