CAShapeLayer和UIBezierPath制作一個圓形進(jìn)度條

本文所有代碼均為swift,但即使你只是一個OCer,我保證你也不會看不懂。文章末尾附上demo地址急但。

上次用CAShapeLayer和UIBezierPath畫了一個企鵝(傳送門),這次還是用這兩樣?xùn)|西搞乏,封裝一個簡單實(shí)用的進(jìn)度條工具。先上一個效果圖:

progress.gif

先來整理一下我們需要做什么戒努,首先要有一個顯示進(jìn)度數(shù)字的label请敦,還要有一個進(jìn)度條,一個進(jìn)度條的底储玫,基本上就是這些侍筛。
第一步,我們需要創(chuàng)建一個繼承UIView的子類撒穷,就像下面:

class ProgressView:UIView {
    override init(frame: CGRect) {
        super.init(frame: frame);
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

然后我們需要的屬性或變量:

    /// 進(jìn)度條
    private var circleLayer:CAShapeLayer!
    /// 顯示進(jìn)度數(shù)字的label
    private var progressLabel:UILabel!
    /// 背景條的寬度
    private let backgroundLineWidth:CGFloat = 8;
    /// 進(jìn)度條的寬度匣椰,比背景條稍寬,不至于露出下面的條端礼,丑
    private let progressLineWidth:CGFloat = 12;
    /// 進(jìn)度
    var progress:CGFloat! = 0.0

然后在初始化方法中禽笑,我們先來使用UIBezierpath制作一個進(jìn)度條的圓形底,但是我們要先確定進(jìn)度條的半徑蛤奥,為了不超出這個view自身的大小佳镜,我們選寬高小的作為進(jìn)度條的直徑,但是UIBezierpath的半徑是從圓心到CAShapeLayer的線的寬度中心點(diǎn)的距離凡桥,所以我們需要減去背景寬度的一半:

        let radius = (self.bounds.width > self.bounds.height ? self.bounds.height/2.0 : self.bounds.width/2.0) - backgroundLineWidth/2.0;
        let layerCenter = CGPointMake(self.bounds.width/2.0, self.bounds.height/2.0);

        // 畫一個圓形的path
        let shadowBezierPath = UIBezierPath(arcCenter: layerCenter, radius: radius, startAngle: 0, endAngle: 2*CGFloat(M_PI), clockwise: true);
        let shadowLayer = CAShapeLayer();
        // 填充色
        shadowLayer.fillColor = UIColor.clearColor().CGColor;
        // 邊框色
        shadowLayer.strokeColor = UIColor.blackColor().CGColor;
        shadowLayer.frame = self.bounds;
        // 邊框的寬度
        shadowLayer.lineWidth = backgroundLineWidth;
        shadowLayer.path = shadowBezierPath.CGPath;
        self.layer.addSublayer(shadowLayer);

這樣蟀伸,我們來創(chuàng)建一個對象,看一下效果。

back_Image.png

這樣我們的進(jìn)度條的底就算做好了啊掏,接下來我們做蓋在上面的進(jìn)度條蠢络,需要注意的是,即使進(jìn)度是0迟蜜,我們也需要展示一點(diǎn)進(jìn)度刹孔,不然太難看。

        circleLayer = CAShapeLayer();
        circleLayer.fillColor = UIColor.clearColor().CGColor;
        circleLayer.strokeColor = UIColor(red: 214/255.0, green: 214/255.0, blue: 214/255.0, alpha: 1.0).CGColor;
        /// 這個是設(shè)置線的頭部是圓角
        circleLayer.lineCap = kCALineCapRound;
        circleLayer.frame = self.bounds;
        circleLayer.lineWidth = progressLineWidth;
        self.layer.addSublayer(circleLayer);
        
        progressLabel = UILabel();
        progressLabel.font = UIFont.boldSystemFontOfSize(14);
        progressLabel.textColor = UIColor.blackColor();
        progressLabel.numberOfLines = 1;
        progressLabel.textAlignment = NSTextAlignment.Center;
        progressLabel.lineBreakMode = NSLineBreakMode.ByTruncatingTail;
        self.addSubview(progressLabel);
        
        ///  這是個記號
        self.progressLabel.text = String(format: "%.0f", self.progress*100);
        self.progressLabel.sizeToFit();
        var labFrame = self.progressLabel.frame;
        labFrame = CGRectMake((self.frame.width - self.progressLabel.frame.width)/2.0, (self.frame.height - self.progressLabel.frame.height)/2.0, self.progressLabel.frame.width, self.progressLabel.frame.height);
            self.progressLabel.frame = labFrame;
            
        var p = self.progress;
        if (self.progress < 0.01) {
                p = 0.01;
        }
        let bezierPath = UIBezierPath(arcCenter: CGPointMake(self.frame.width/2.0, self.frame.height/2.0), radius: radius, startAngle: CGFloat(-M_PI_2), endAngle: p*360/180*CGFloat(M_PI) - CGFloat(M_PI_2), clockwise: true);
        self.circleLayer.path = bezierPath.CGPath;

效果如下:

progress_Image.png

接下來我們需要做的就是在改變progress的時候小泉,相應(yīng)的改變進(jìn)度的弧度芦疏,因此,我們先把以上代碼中的記號下面的代碼拉出來放一個方法里微姊,在progress的didSet方法里酸茴,調(diào)用這個方法即可,比如這個方法叫setProgress:

    /// 進(jìn)度
    var progress:CGFloat! = 0.0 {
        didSet {
            if (progress >= 1) {
                progress = 1;
            }
            self.setProgress();
        }
    }

到這兢交,這個進(jìn)度條控件基本已經(jīng)做好了薪捍,但是還不夠完善,比如再用NSURLSession下載的代理中配喳,因?yàn)橄螺d的代理方法并不在主線程中酪穿,在代理方法中直接改變progress,就會有問題晴裹,我們可以把setProgress中的代碼放到主線程中被济。

        dispatch_async(dispatch_get_main_queue()) { 
                // setProgress
        }

下篇預(yù)告:

indicator.gif

demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涧团,隨后出現(xiàn)的幾起案子只磷,更是在濱河造成了極大的恐慌,老刑警劉巖泌绣,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钮追,死亡現(xiàn)場離奇詭異,居然都是意外死亡阿迈,警方通過查閱死者的電腦和手機(jī)元媚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苗沧,“玉大人刊棕,你說我怎么就攤上這事〈眩” “怎么了鞠绰?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長飒焦。 經(jīng)常有香客問我蜈膨,道長屿笼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任翁巍,我火速辦了婚禮驴一,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灶壶。我一直安慰自己肝断,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布驰凛。 她就那樣靜靜地躺著胸懈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恰响。 梳的紋絲不亂的頭發(fā)上趣钱,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機(jī)與錄音胚宦,去河邊找鬼首有。 笑死,一個胖子當(dāng)著我的面吹牛枢劝,可吹牛的內(nèi)容都是我干的井联。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼您旁,長吁一口氣:“原來是場噩夢啊……” “哼烙常!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鹤盒,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤军掂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后昨悼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跃洛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年率触,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汇竭。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡葱蝗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出细燎,到底是詐尸還是另有隱情两曼,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布玻驻,位于F島的核電站悼凑,受9級特大地震影響偿枕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜户辫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一渐夸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渔欢,春花似錦墓塌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至垫挨,卻和暖如春韩肝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棒拂。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工伞梯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帚屉。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓谜诫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親攻旦。 傳聞我的和親對象是個殘疾皇子喻旷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

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

  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議。它實(shí)...
    香橙柚子閱讀 23,862評論 8 183
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫牢屋、插件且预、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • Drosha閱讀 169評論 3 0
  • 性能測試 1.連接速度測試 用戶連接到Web應(yīng)用系統(tǒng)的速度根據(jù)上網(wǎng)方式的變化而變化,他們或許是電話撥號烙无,或是寬帶上...
    alston123閱讀 276評論 0 1
  • 今天是8月15截酷,是我遠(yuǎn)離家鄉(xiāng)之后過的第一個中秋節(jié)涮拗。我住的是公司宿舍,同寢室的都是本地人迂苛,都回家去了三热。 早上6...
    何棠月瑟閱讀 376評論 0 1