扇形進(jìn)度條 - iOS

繪制扇形進(jìn)度條

背景:上傳文件的時(shí)候闪水,需要有上傳進(jìn)度报破,這次需要一個(gè)扇形的進(jìn)度條,示例圖如下:


背景.jpg

廢話不多說蚤吹,上代碼:

/**
 扇形圖進(jìn)度條
 角度:可選擇起始角度:SLSectorStartAngle:top left bottom and right
 旋轉(zhuǎn):順時(shí)針旋轉(zhuǎn)
 半徑: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

/// 構(gòu)造方法
/// @param startAngle 初始角度
- (instancetype)initWithStartAngle:(SLSectorStartAngle)startAngle radius:(CGFloat)radius fillColor:(UIColor *)fillColor;

/// 進(jìn)度
@property(nonatomic, assign) CGFloat progress;

/// 配置邊框顏色和寬度
/// @param borderColor 邊框顏色
/// @param borderWidth 邊框?qū)挾?- (void)configBorderWithColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

/// 沒有進(jìn)度時(shí)例诀,是否需要占位線(如果需要下面的繪制外圈的圓圈,一般都需要繪制默認(rèn)占位線)
@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;
/// 邊框粗細(xì)
@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 - 更新進(jìn)度

- (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];
}

// 繪制進(jìn)度條
- (void)drawProgress {
    // 中心點(diǎn)
    CGPoint origin = CGPointMake(_radius/2, _radius/2);
    // 半徑
    CGFloat radius = _radius/2;
    // 起始角度
    CGFloat startAngle = [self fetchStartAngle];
    // 結(jié)束角度
    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; // 默認(rèn)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

以上代碼的調(diào)用方式如下:


#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

按照上面代碼跑起來裁着,示例圖如下:


demo.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末繁涂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子二驰,更是在濱河造成了極大的恐慌扔罪,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桶雀,死亡現(xiàn)場(chǎng)離奇詭異矿酵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)矗积,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門全肮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棘捣,你說我怎么就攤上這事辜腺。” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵哪自,是天一觀的道長丰包。 經(jīng)常有香客問我,道長壤巷,這世上最難降的妖魔是什么邑彪? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮胧华,結(jié)果婚禮上寄症,老公的妹妹穿的比我還像新娘。我一直安慰自己矩动,他們只是感情好有巧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悲没,像睡著了一般篮迎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上示姿,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天甜橱,我揣著相機(jī)與錄音,去河邊找鬼栈戳。 笑死岂傲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的子檀。 我是一名探鬼主播镊掖,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼褂痰!你這毒婦竟也來了亩进?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤脐恩,失蹤者是張志新(化名)和其女友劉穎镐侯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驶冒,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苟翻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骗污。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崇猫。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖需忿,靈堂內(nèi)的尸體忽然破棺而出诅炉,到底是詐尸還是另有隱情蜡歹,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布涕烧,位于F島的核電站月而,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏议纯。R本人自食惡果不足惜父款,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞻凤。 院中可真熱鬧憨攒,春花似錦、人聲如沸阀参。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛛壳。三九已至杏瞻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衙荐,已是汗流浹背伐憾。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赫模,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓蒸矛,卻偏偏與公主長得像瀑罗,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子雏掠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容