在這濃濃的鞭炮聲中,迎來了這個(gè)系列的最后一篇掉丽。哈哈~這是多么有紀(jì)念意義的春節(jié)呀跌榔。
今天我們來寫一個(gè)小小的Demo,來演練一下通過OC繪圖捶障,根據(jù)進(jìn)度自己繪制出來一個(gè)進(jìn)度條僧须,或者進(jìn)度扇形、進(jìn)度球形项炼。
在此之前担平,分享了一些關(guān)于繪圖方面的基礎(chǔ)《Р浚可以通過傳輸門快捷進(jìn)入:
1. 效果展示及思維導(dǎo)圖
效果展示:
效果展示.gif
思維導(dǎo)圖:
進(jìn)度條、進(jìn)度扇形拌禾、進(jìn)度球的思維導(dǎo)圖.png
2. 項(xiàng)目準(zhǔn)備工作
- 為了省事取胎,我們所有的繪圖都是在SotryBoard上面進(jìn)行。如果有興趣的同學(xué)可以自己通過代碼約束的方式實(shí)現(xiàn)蹋砚。
- 用一個(gè)UISlider來模擬進(jìn)度下載扼菠,這樣可以通過拖動(dòng)滑桿摄杂,感受到下載的過程坝咐。
- 實(shí)際開發(fā)中的提醒:在實(shí)際中,下載進(jìn)度通常都不會放在主線程上析恢,所以子線程獲得下載的進(jìn)度之后墨坚,不要忘記回到主線程刷新UI。
- 我們這些模擬都是通過滑桿的,所以所有的操作不涉及到多線程泽篮。
3. 進(jìn)度條的實(shí)現(xiàn)
進(jìn)度條我們這里就直接使用了SB的UIProgressView這個(gè)控件盗尸。如果覺得不好看的同學(xué),可以通過自定義線段+Label的方式實(shí)現(xiàn)帽撑。繪制線段的部分可以參考上一篇分享里面有泼各,同時(shí)也可以參考下面繪制扇形或者球形進(jìn)度指示器的部分。
安全賦值
- 我們通晨骼看到的下載進(jìn)度都是0%~100%這種表達(dá)方式扣蜻,所以表示下載進(jìn)度的數(shù)值范圍是0~1.
- 然而UISlider的范圍是可以自定義的,所以我們需要做一下數(shù)值的安全處理及塘,讓最終下載進(jìn)度的數(shù)值范圍在0~1之間莽使。
一行代碼搞定:
@property (weak, nonatomic) IBOutlet UIProgressView *lineView;
- (IBAction)sliderValueChanged:(UISlider *)sender {
// 對進(jìn)度條進(jìn)行賦值,同時(shí)對數(shù)值進(jìn)行安全處理
self.lineView.progress = (sender.value - sender.minimumValue) / (sender.maximumValue - sender.minimumValue);
}
完成效果:
progressLine.gif
4. 扇形進(jìn)度指示器
- 定義扇形的中心笙僚、扇形的半徑芳肌、扇形的起點(diǎn);
- 計(jì)算扇形的結(jié)束位置:起點(diǎn) + 進(jìn)度百分比*2PI
- 根據(jù)起始點(diǎn)肋层、原點(diǎn)亿笤、半徑繪制弧線.
- 從弧線結(jié)束為止繪制一條線段到圓心。這樣系統(tǒng)會自動(dòng)閉合圖形栋猖,繪制一條從圓心到弧線起點(diǎn)的線段责嚷。
- 設(shè)置扇形的填充模式、填充顏色掂铐。
- 給View設(shè)置一個(gè)進(jìn)度的屬性罕拂,用來讓外界賦值。
- 重新進(jìn)度屬性的set方法全陨,為的是給進(jìn)度賦值的時(shí)候可以時(shí)時(shí)刷新UI爆班,同時(shí)用文字Label顯示進(jìn)度的具體數(shù)值。
代碼如下:
@interface SectorProgress : UIView
@property(assign,nonatomic)CGFloat progress;
@property(weak,nonatomic) IBOutlet UILabel *progressLabel;
@end
- (void)drawRect:(CGRect)rect {
// 定義扇形中心
CGPoint origin = CGPointMake(100, 100);
// 定義扇形半徑
CGFloat radius = 100.0f;
// 設(shè)定扇形起點(diǎn)位置
CGFloat startAngle = - M_PI_2;
// 根據(jù)進(jìn)度計(jì)算扇形結(jié)束位置
CGFloat endAngle = startAngle + self.progress * M_PI * 2;
// 根據(jù)起始點(diǎn)辱姨、原點(diǎn)柿菩、半徑繪制弧線
UIBezierPath *sectorPath = [UIBezierPath bezierPathWithArcCenter:origin radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
// 從弧線結(jié)束為止繪制一條線段到圓心。這樣系統(tǒng)會自動(dòng)閉合圖形雨涛,繪制一條從圓心到弧線起點(diǎn)的線段枢舶。
[sectorPath addLineToPoint:origin];
// 設(shè)置扇形的填充顏色
[[UIColor darkGrayColor] set];
// 設(shè)置扇形的填充模式
[sectorPath fill];
}
//重寫progress的set方法,可以在賦值的同時(shí)給label賦值
- (void)setProgress:(CGFloat)progress{
_progress = progress;
// 對label進(jìn)行賦值
self.progressLabel.text = [NSString stringWithFormat:@"%0.2f%%",progress * 100];
// 賦值結(jié)束之后要刷新UI替久,不然看不到扇形的變化
[self setNeedsDisplay];
}
完成效果:
sectorProgress.gif
5. 球形指示器
球形指示器幾乎和扇形的一樣凉泄,只是在繪制的時(shí)候計(jì)算角度稍稍有點(diǎn)點(diǎn)點(diǎn)點(diǎn)不一樣而已。
- 定義扇形的中心蚯根、扇形的半徑后众;
- 定義起始點(diǎn)位置的屬性,用來賦值;
- 根據(jù)起始點(diǎn)蒂誉、原點(diǎn)教藻、半徑繪制弧線.
- 系統(tǒng)會自動(dòng)的從起點(diǎn)到終點(diǎn)進(jìn)行閉合,形成一個(gè)球形右锨。
- 設(shè)置球形的填充模式括堤、填充顏色。
- 為了讓球形看起來更自然绍移,要在球形的外面填充一個(gè)空心描邊的圓形痊臭。
- 給View設(shè)置一個(gè)進(jìn)度的屬性,用來讓外界賦值登夫。
- 重新進(jìn)度屬性的set方法广匙,這里和扇形指示器有一點(diǎn)點(diǎn)不一樣。在這里我們需要根據(jù)進(jìn)度計(jì)算球形的起始位置恼策,同時(shí)刷新UI鸦致,對文字Label進(jìn)行賦值。
球形是從下往上進(jìn)行增長的涣楷,所以計(jì)算角度的時(shí)候起點(diǎn)要從PI/2開始分唾。
@interface BallProgress ()
@property(assign,nonatomic)CGFloat progress;
@property(assign,nonatomic)CGFloat startAngle;
@property(assign,nonatomic)CGFloat endAngle;
@property(weak,nonatomic) IBOutlet UILabel *progressLabel;
@end
- (void)drawRect:(CGRect)rect {
CGPoint origin = CGPointMake(100, 100);
CGFloat radius = 95.0f;
UIBezierPath *ballPath = [UIBezierPath bezierPathWithArcCenter:origin radius:radius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
[[UIColor purpleColor]set];
[ballPath fill];
// 在球形的外面繪制一個(gè)描邊空心的圓形,不然很難看
UIBezierPath *strokePath = [UIBezierPath bezierPathWithArcCenter:origin radius:radius startAngle:0 endAngle:-0.00000001 clockwise:YES];
[[UIColor lightGrayColor]set];
[strokePath stroke];
}
- (void)setProgress:(CGFloat)progress{
_progress = progress;
// 設(shè)置起始點(diǎn)狮斗,位置是根據(jù)進(jìn)度動(dòng)態(tài)變換的
self.startAngle = M_PI_2 - progress * M_PI;
self.endAngle = M_PI_2 + progress * M_PI;
self.progressLabel.text = [NSString stringWithFormat:@"%0.2f%%",progress * 100];
[self setNeedsDisplay];
}
最終完成效果:
ballProgress.gif
好了绽乔,過年不戳更,新年有大吉~加油碳褒!