很多地方都會使用環形進度條,這裏我們就繼承自UIView,自定義一個環形進度條控件,可以設置進度條顏色,寬度,進度,動畫效果。
我們自定義一個環型圖層添加到UIView的圖層上去,從而實現環形控件。我們使用CAShapeLayer類創建自己的圖層。它有幾個常用的屬性:frame 尺寸,fillColor圖層填充色,strokeColor圖層邊界的顏色,lineWidth 邊界線寬,path 圖層路徑通過這個路徑我們可以控制圖層的形狀在這裏我們會給圖層一個圓形路徑讓整個視圖呈現環狀,strokeStart簡單點理解就是繪製的起點在這我們把它作爲初始進度,strokeEnd繪製的終點它可以作爲結束的進度。
我們先創建一個圖層,完全繪製作爲進度條的底部圖形:
let path = UIBezierPath(ovalInRect: bounds).CGPath
let trackLayer = CAShapeLayer()
trackLayer.frame = bounds
trackLayer.fillColor = UIColor.clearColor().CGColor
trackLayer.strokeColor = progressProperty.trackColor.CGColor
trackLayer.lineWidth = progressProperty.width
trackLayer.path = path
layer.addSublayer(trackLayer)
let path = UIBezierPath(ovalInRect: bounds).CGPath //這是我們以視圖尺寸創建的一個內切圓,將這個圓作爲路徑。
接下來我們再創建一個圖層,表示進度條視圖的進度,並且給這個圖層一個初始的進度
progressLayer.frame = bounds
progressLayer.fillColor = UIColor.clearColor().CGColor
progressLayer.strokeColor = progressProperty.progressColor.CGColor
progressLayer.lineWidth = progressProperty.width
progressLayer.path = path
progressLayer.strokeStart = progressProperty.progressStart
progressLayer.strokeEnd = progressProperty.progressEnd
layer.addSublayer(progressLayer)
最後我們給表示進度的圖層添加動畫屬性,使用CATransaction動畫:
CATransaction.begin()
CATransaction.setDisableActions(!animate)
CATransaction.setAnimationDuration(time)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut))
progressLayer.strokeEnd = progress
CATransaction.commit()
下面我們在控制器裏面使用這個自定義控件創建兩個進度條進行測試體驗效果:
var progressView1:UIAnnularProgress?
var progressView2:UIAnnularProgress?
var progress:CGFloat?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
progress = 0.25
progressView1 = UIAnnularProgress(propressProperty:ProgressProperty(width: 5, progressEnd: 0.1, progressColor: UIColor.redColor()), frame:CGRectMake(50,100,200,200))
self.view.addSubview(progressView1!)
progressView2 = UIAnnularProgress(frame: CGRectMake(50,350,150,150))
self.view.addSubview(progressView2!)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
progress! = progress! + 0.1
if progress! >= 1.0 {
progress! = 0
}
progressView1?.setProgress(progress!, time:0.6, animate: false)
progressView2?.setProgress(progress!, time:0.6, animate: true)
}
以下是自定義進度條控件的源碼:
//
// UIAnnularProgress.swift
// 環形進度條
//
// Created by 句芒 on 16/9/26.
// Copyright © 2016年 fanwei. All rights reserved.
//
import UIKit
struct ProgressProperty{
var width:CGFloat
var trackColor:UIColor
var progressColor :UIColor
var progressStart:CGFloat
var progressEnd:CGFloat
init(width:CGFloat,progressEnd:CGFloat,progressColor:UIColor) {
self.width = width
self.progressEnd = progressEnd
self.progressColor = progressColor
trackColor = UIColor.grayColor()
progressStart = 0.0
}
init() {
width = 10
trackColor = UIColor.grayColor()
progressColor = UIColor.greenColor()
progressStart = 0.0
progressEnd = 0.25
}
}
class UIAnnularProgress: UIView {
var progressProperty = ProgressProperty.init()
private let progressLayer = CAShapeLayer()
init(propressProperty:ProgressProperty,frame:CGRect) {
self.progressProperty = propressProperty
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(rect: CGRect) {
let path = UIBezierPath(ovalInRect: bounds).CGPath
let trackLayer = CAShapeLayer()
trackLayer.frame = bounds
trackLayer.fillColor = UIColor.clearColor().CGColor
trackLayer.strokeColor = progressProperty.trackColor.CGColor
trackLayer.lineWidth = progressProperty.width
trackLayer.path = path
layer.addSublayer(trackLayer)
progressLayer.frame = bounds
progressLayer.fillColor = UIColor.clearColor().CGColor
progressLayer.strokeColor = progressProperty.progressColor.CGColor
progressLayer.lineWidth = progressProperty.width
progressLayer.path = path
progressLayer.strokeStart = progressProperty.progressStart
progressLayer.strokeEnd = progressProperty.progressEnd
layer.addSublayer(progressLayer)
}
func setProgress(progress:CGFloat,time:CFTimeInterval,animate:Bool) {
CATransaction.begin()
CATransaction.setDisableActions(!animate)
CATransaction.setAnimationDuration(time)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut))
progressLayer.strokeEnd = progress
CATransaction.commit()
}
}