圆形进度条,可设置内外环,多彩

原创 2015年12月23日 16:30:25

今天做一个健身的项目,客户需要一个圆形的进度条来查看个人的运动记录等,做了一些功课之后贴出代码大家一起分享下


代码比较长,多,在这里我先放上demo下载地址  http://download.csdn.net/detail/a174455171/9517479

新建一个继承UIView类

.h文件

@interface MyProgressView : UIView


@property (strong,nonatomic)UILabel *textLabel;



@property (nonatomic)double progress;


@property (nonatomic)NSInteger showTextUI_APPEARANCE_SELECTOR;

@property (nonatomic)NSInteger roundedHeadUI_APPEARANCE_SELECTOR;

@property (nonatomic)NSInteger showShadowUI_APPEARANCE_SELECTOR;


@property (nonatomic)CGFloat thicknessRatioUI_APPEARANCE_SELECTOR;


/**

 *  设置内环和外环时使用

 */

@property (nonatomic,strong) UIColor *innerBackgroundColorUI_APPEARANCE_SELECTOR;

@property (nonatomic,strong) UIColor *outerBackgroundColorUI_APPEARANCE_SELECTOR;


@property (nonatomic,strong) UIFont *fontUI_APPEARANCE_SELECTOR;


/**

 *  只有一种颜色时使用

 */

@property (nonatomic,strong) UIColor *progressFillColorUI_APPEARANCE_SELECTOR;


@property (nonatomic,strong) UIColor *progressTopGradientColorUI_APPEARANCE_SELECTOR;

@property (nonatomic,strong) UIColor *progressBottomGradientColorUI_APPEARANCE_SELECTOR;


@property (strong,nonatomic)NSArray *colorArray;       //多彩时使用

@property (strong,nonatomic)NSArray *shadeArray;       //每个颜色处于的位置

@property (nonatomic,readonly)CGFloat *back;


/**

 *  设置多彩圆环

 *

 *  @param colorArray 颜色数组

 *  @param shadeArray 每个颜色处于的位置

 */

-(void)setColorArray:(NSArray *)colorArray shadeArray:(NSArray *)shadeArray;


.m文件

#import <math.h>


#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)


@interface MyProgressView ()


@property (nonatomic)UIBezierPath *path;

@property (nonatomic)CAShapeLayer *shapeLayer;

@property (nonatomic)UIBezierPath *path1;

@property (nonatomic)CAShapeLayer *shapeLayer1;


@property (strong,nonatomic)UIImageView *imageView;






@end


@implementation MyProgressView


+ (void)initialize

{

    if (self == [MyProgressViewclass])

    {

        id appearance = [selfappearance];

        

        [appearance setShowText:NO];//用来控制是否显示显示label

        [appearance setRoundedHead:YES];//用来控制是否对进度两边进行处理

        [appearance setShowShadow:YES];//控制圆环进度条的样式

        

        [appearance setThicknessRatio:0.1f];//圆环进度条的宽度

        

        [appearance setInnerBackgroundColor:nil];

        [appearance setOuterBackgroundColor:nil];

        

//        [appearance setProgressFillColor:[UIColor redColor]];//整个进度条颜色

//        [appearance setProgressTopGradientColor:[UIColor greenColor]];//进度条前半部分颜色

//        [appearance setProgressBottomGradientColor:[UIColor redColor]];//进度条后半部分颜色

        [appearance setBackgroundColor:[UIColorclearColor]];

    }

}


- (void)drawRect:(CGRect)rect

{

    // Calculate position of the circle

    CGFloat progressAngle = _progress * 360.0 - 90;

    CGPoint center = CGPointMake(rect.size.width /2.0f, rect.size.height /2.0f);

    CGFloat radius = MIN(rect.size.width, rect.size.height) /2.0f;

    

    CGRect square;

    if (rect.size.width > rect.size.height)

    {

        square = CGRectMake((rect.size.width - rect.size.height) /2.0, 0.0, rect.size.height, rect.size.height);

    }

    else

    {

        square = CGRectMake(0.0, (rect.size.height - rect.size.width) / 2.0, rect.size.width, rect.size.width);

    }

    

    //进度条宽度

    CGFloat circleWidth = radius * _thicknessRatio;

    CGContextRef context =UIGraphicsGetCurrentContext();

    CGContextSaveGState(context);

    

    if (_innerBackgroundColor)

    {

        //内环

        // Fill innerCircle with innerBackgroundColor

        UIBezierPath *innerCircle = [UIBezierPathbezierPathWithArcCenter:center

                                                                   radius:radius - circleWidth

                                                               startAngle:2*M_PI

                                                                 endAngle:0.0

                                                                clockwise:YES];

        

        [_innerBackgroundColorsetFill];

        

        [innerCircle fill];

    }

    

    if (_outerBackgroundColor)

    {

        //外环

        // Fill outerCircle with outerBackgroundColor

        UIBezierPath *outerCircle = [UIBezierPathbezierPathWithArcCenter:center

                                                                   radius:radius

                                                               startAngle:0.0

                                                                 endAngle:2*M_PI

                                                                clockwise:NO];

        [outerCircle addArcWithCenter:center

                               radius:radius - circleWidth

                           startAngle:2*M_PI

                             endAngle:0.0

                            clockwise:YES];

        

        [_outerBackgroundColorsetFill];

        

        [outerCircle fill];

    }

    

    if (_showShadow)

    {

        //圆环背景处理

        CGFloat locations[5] = {0.0f, 0.33f,0.66f, 1.0f };

//                NSArray *gradientColors = @[

//                                            (id)[[UIColor colorWithWhite:0.3 alpha:0.5] CGColor],

//                                            (id)[[UIColor colorWithWhite:0.9 alpha:0.0] CGColor],

//                                            (id)[[UIColor colorWithWhite:0.9 alpha:0.0] CGColor],

//                                            (id)[[UIColor colorWithWhite:0.3 alpha:0.5] CGColor],

//                                            ];

        

        NSArray *gradientColors = @[

                                    (id)[[UIColorcolorWithWhite:0.7alpha:1] CGColor],

                                    (id)[[UIColorcolorWithWhite:0.7alpha:1] CGColor],

                                    (id)[[UIColorcolorWithWhite:0.7alpha:1] CGColor],

                                    (id)[[UIColorcolorWithWhite:0.7alpha:1] CGColor],

                                    ];

        

        CGColorSpaceRef rgb =CGColorSpaceCreateDeviceRGB();

        CGGradientRef gradient = CGGradientCreateWithColors(rgb, (__bridgeCFArrayRef)gradientColors, locations);

        CGContextDrawRadialGradient(context, gradient, center, radius - circleWidth, center, radius,0);

        CGGradientRelease(gradient);

        CGColorSpaceRelease(rgb);

    }

    

    if (_showText)

    {

        if (!_progress) {

            return;

        }

        if ([selfviewWithTag:5]) {

            [_textLabelremoveFromSuperview];

        }

        //中间显示label

        _textLabel = [[UILabelalloc] init];

        //字符串处理

        NSString *str = [NSStringstringWithFormat:@"%0.2f%%\n收益率",_progress * 100.0];

        NSMutableAttributedString *progressStr = [[NSMutableAttributedStringalloc] initWithString:str];

        //6位字符 颜色

        [progressStr addAttribute:NSForegroundColorAttributeNamevalue:[UIColorredColor] range:NSMakeRange(0,6)];

        //第七位向后的3个字符颜色

        [progressStr addAttribute:NSForegroundColorAttributeNamevalue:[UIColorblackColor] range:NSMakeRange(7,3)];

        [progressStr addAttribute:NSFontAttributeNamevalue:[UIFontboldSystemFontOfSize:16.0]range:NSMakeRange(0,6)];

        [progressStr addAttribute:NSFontAttributeNamevalue:[UIFontsystemFontOfSize:13]range:NSMakeRange(7,3)];

        _textLabel.attributedText = progressStr;

        _textLabel.numberOfLines =0;

        _textLabel.bounds =CGRectMake(0,0, 100, 50);

        _textLabel.center =CGPointMake(self.bounds.size.width/2.0,self.bounds.size.height/2.0);

        _textLabel.tag =5;

        _textLabel.textAlignment =NSTextAlignmentCenter;

        [self addSubview:_textLabel];

        

    }

    

    UIBezierPath *path = [UIBezierPathbezierPath];

    

    

    [path appendPath:[UIBezierPathbezierPathWithArcCenter:center

                                                    radius:radius

                                                startAngle:DEGREES_TO_RADIANS(-90)

                                                  endAngle:DEGREES_TO_RADIANS(progressAngle)

                                                 clockwise:YES]];

    

    if (_roundedHead)

    {

        //终点处理  也可以给终点放置一些图片等

        CGPoint point;

        point.x = (cos(DEGREES_TO_RADIANS(progressAngle)) * (radius - circleWidth/2)) + center.x;

        point.y = (sin(DEGREES_TO_RADIANS(progressAngle)) * (radius - circleWidth/2)) + center.y;

        

        [path addArcWithCenter:point

                        radius:circleWidth/2

                    startAngle:DEGREES_TO_RADIANS(progressAngle)

                      endAngle:DEGREES_TO_RADIANS(270.0 + progressAngle -90.0)

                     clockwise:YES];

    }

    

    [path addArcWithCenter:center

                    radius:radius-circleWidth

                startAngle:DEGREES_TO_RADIANS(progressAngle)

                  endAngle:DEGREES_TO_RADIANS(-90)

                 clockwise:NO];

    //起始点添加分割线

//    UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(radius, 0, 1, circleWidth)];

//    lineView.backgroundColor = [UIColor whiteColor];

//    [self addSubview:lineView];

    

    if (_roundedHead)

    {

        //起始点处理

        //        CGPoint point;

        //        point.x = (cos(DEGREES_TO_RADIANS(-90)) * (radius - circleWidth/2)) + center.x;

        //        point.y = (sin(DEGREES_TO_RADIANS(-90)) * (radius - circleWidth/2)) + center.y;

        //

        //        [path addArcWithCenter:point

        //                        radius:circleWidth/2

        //                    startAngle:DEGREES_TO_RADIANS(90)

        //                      endAngle:DEGREES_TO_RADIANS(-90)

        //                     clockwise:NO];

    }

    

    [path closePath];

    //进度条颜色处理

    if (_progressFillColor)

    {

        [_progressFillColorsetFill];

        [path fill];

    }

    elseif (_progressTopGradientColor &&_progressBottomGradientColor)

    {

        [path addClip];

        

        NSArray *backgroundColors = @[

                                      (id)[_progressTopGradientColorCGColor],

                                      (id)[_progressBottomGradientColorCGColor],

                                      ];

        

        CGFloat backgroudColorLocations[2] = {0.0f,1.0f};

        

        CGColorSpaceRef rgb =CGColorSpaceCreateDeviceRGB();

        CGGradientRef backgroundGradient = CGGradientCreateWithColors(rgb, (__bridgeCFArrayRef)(backgroundColors), backgroudColorLocations);

        CGContextDrawLinearGradient(context,

                                    backgroundGradient,

                                    CGPointMake(0.0f, square.origin.y),

                                    CGPointMake(0.0f, square.size.height),

                                    0);

        CGGradientRelease(backgroundGradient);

        CGColorSpaceRelease(rgb);

    }

    else

    {

        [path addClip];

        

        NSMutableArray *backgroundColors = [[NSMutableArrayalloc] init];

        for (UIColor *colorin _colorArray)

        {

            [backgroundColors addObject:(id)[colorCGColor]];

        }

        CGColorSpaceRef rgb =CGColorSpaceCreateDeviceRGB();

        CGGradientRef backgroundGradient = CGGradientCreateWithColors(rgb, (__bridgeCFArrayRef)(backgroundColors), _back);

        CGContextDrawLinearGradient(context,

                                    backgroundGradient,

                                    CGPointMake(0.0f, square.origin.y),

                                    CGPointMake(0.0f, square.size.height),

                                    0);

        CGGradientRelease(backgroundGradient);

        CGColorSpaceRelease(rgb);

    }

    CGContextRestoreGState(context);

}


#pragma mark - Setter

//设置进度

- (void)setProgress:(double)progress

{

    _progress = MIN(1.0,MAX(0.0, progress));

    

    [selfsetNeedsDisplay];

}


#pragma mark - UIAppearance


- (void)setShowText:(NSInteger)showText

{

    _showText = showText;

    

    [selfsetNeedsDisplay];

}


- (void)setRoundedHead:(NSInteger)roundedHead

{

    _roundedHead = roundedHead;

    

    [selfsetNeedsDisplay];

}


- (void)setShowShadow:(NSInteger)showShadow

{

    _showShadow = showShadow;

    

    [selfsetNeedsDisplay];

}

//进度条宽度与半径之比

- (void)setThicknessRatio:(CGFloat)thickness

{

    _thicknessRatio = MIN(MAX(0.0f, thickness),1.0f);

    

    [selfsetNeedsDisplay];

}

//内环

- (void)setInnerBackgroundColor:(UIColor *)innerBackgroundColor

{

    _innerBackgroundColor = innerBackgroundColor;

    

    [selfsetNeedsDisplay];

}

//外环

- (void)setOuterBackgroundColor:(UIColor *)outerBackgroundColor

{

    _outerBackgroundColor = outerBackgroundColor;

    

    [selfsetNeedsDisplay];

}

//进度条颜色

- (void)setProgressFillColor:(UIColor *)progressFillColor

{

    _progressFillColor = progressFillColor;

    

    [selfsetNeedsDisplay];

}

//进度条前半部分颜色

- (void)setProgressTopGradientColor:(UIColor *)progressTopGradientColor

{

    _progressTopGradientColor = progressTopGradientColor;

    

    [selfsetNeedsDisplay];

}

//进度条后半部分颜色

- (void)setProgressBottomGradientColor:(UIColor *)progressBottomGradientColor

{

    _progressBottomGradientColor = progressBottomGradientColor;

    

    [selfsetNeedsDisplay];

}


-(void)setColorArray:(NSArray *)colorArray

{

    _colorArray = colorArray;

    

    [selfsetNeedsDisplay];

}


-(void)setShadeArray:(NSArray *)shadeArray

{

    _shadeArray = shadeArray;

    

    [selfsetNeedsDisplay];

}


-(void)setColorArray:(NSArray *)colorArray shadeArray:(NSArray *)shadeArray

{

    _colorArray = colorArray;

    _shadeArray = shadeArray;

    _back = (CGFloat *)malloc(shadeArray.count*sizeof(CGFloat));

    for (int i=0; i<shadeArray.count; i++)

    {

        _back[i] = [_shadeArray[i]floatValue];

    }

    [selfsetNeedsDisplay];

}


其中有时候会碰到一些需要一个小点或者在进度终点做一些处理,代码里面都有说明


如何实现一个环形进度条

在之前的工作中,有一个需求是判断已用和剩余油量用环形进度条的方式展示的。改方面的数据是通过串口从底层获取过来的,这边我就随便拿个数来填充就好了。当时由于上级的要求就自己写了一个比较简单的出来。好的,那...
  • u013171283
  • u013171283
  • 2016年03月09日 18:47
  • 1053

自定义圆形进度条实现动态显示指定进度

首先得写一个类RoundProgress继承View,重写其中onMeasure()和onDraw()方法。在onMeasure()里获取当前画布的宽度。 在onDraw()方法里主要绘制如下三部分...
  • xiaoyantan
  • xiaoyantan
  • 2016年11月13日 16:45
  • 1916

圆形百分比进度条(避坑笔记)

最近在写项目的时候发现要写一个圆形进度条,本来想着自己写一个吧,写完后发现有坑啊,关键是还是一个大坑,项目中使用的刷新控件是WaterDropListView然后发现进度条显示的数据一直有问题,一开始...
  • u012304076
  • u012304076
  • 2016年08月10日 11:29
  • 711

Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)

很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己来自定义一个能满足我们需求的View,自定义View我们需要先继承View,添加类的构造方法,重写父类View的一些方法,例如o...
  • xiaanming
  • xiaanming
  • 2013年08月26日 14:36
  • 174693

Unity圆环进度条制作

0. 背景最近有个在Unity中制作圆环进度条的需求,并在圆中显示进度数值,类似于图1: 图1. 圆环进度条平时制作直线的进度条比较多,突然要求做个圆环的有些不适应。不过,这个需求google一...
  • tab_space
  • tab_space
  • 2016年06月28日 14:24
  • 6559

实现各种圆形或者半圆形菜单,以及圆形进度条。

  • 2014年06月04日 15:32
  • 2.46MB
  • 下载

Android 自定义漂亮的圆形进度条

公司有这样一个需求所以现在就将它抽取出来不废话,直接上代码 自定义view import android.content.Context; import android.content.res.Typ...
  • qq_32519693
  • qq_32519693
  • 2017年08月05日 16:57
  • 2485

自定义一个带进度值的圆形进度条

项目中有时候我们为了博得用户的眼球,需要自定义一些好看的控件,下面记录一个自定义带进度值的圆形进度条 先上效果 下面记录具体的实现过程 在Android studio下新建一个proje...
  • u010918416
  • u010918416
  • 2017年02月27日 22:53
  • 419

jquery写的一个圆形动画加载进度条

Canvas绘图 200px" height="200px">0% $(document).ready(function() { //drawProcess(); i = 0; ...
  • qq_30552993
  • qq_30552993
  • 2016年02月04日 10:40
  • 4340

【Android进度条】三种方式实现自定义圆形进度条ProgressBar

一、通过动画实现定义res/anim/loading.xml如下: 二、通过自定义颜色实现定义res/drawable/progress_small.xm...
  • feng88724
  • feng88724
  • 2012年03月29日 22:02
  • 81475
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:圆形进度条,可设置内外环,多彩
举报原因:
原因补充:

(最多只允许输入30个字)