学习文章
效果
简单原理
用 CAGradientLayer
来实现颜色的过渡,创建一个 ProgressColor 的对象,专门来给 CAGradientLayer
提供颜色等相关值. 创建 ColorProgressView ,作为呈现进度条的视图,用以组合 CAGradientLayer
,并实现颜色移动. 用 UIView 动画呈现进度,使其生动.
源码
ProgressColor.swift
import UIKit
class ProgressColor: NSObject {
var m_colors : [AnyObject]?
var m_startPoint : CGPoint?
var m_endPoint : CGPoint?
var m_duration : NSTimeInterval?
func loopMove() -> [AnyObject] {
var tempArray : Array = self.m_colors!
let last = tempArray.last
tempArray.removeLast()
tempArray.insert(last!, atIndex: 0)
return tempArray
}
override init() {
super.init()
self.m_startPoint = CGPoint(x: 0, y: 0.5)
self.m_endPoint = CGPoint(x: 1, y: 0.5)
self.m_duration = 0.1
self.m_colors = [AnyObject]()
for var deg : Int = 0; deg <= 360; deg += 5 {
let color = UIColor(hue: CGFloat(deg) / 360.0, saturation: 1.0, brightness: 1.0, alpha: 1.0)
self.m_colors!.append(color.CGColor)
}
}
}
extension ProgressColor {
// 提供一种生成红色过渡的ProgressColor
class func redGradientColor() -> ProgressColor {
let progressColor = ProgressColor()
var array = [AnyObject]()
array.append(UIColor(red: 0.2, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.2, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.3, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.4, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.5, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.6, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.7, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.8, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.9, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 1, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.9, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.8, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.7, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.6, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.5, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.4, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.3, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.2, green: 0, blue: 0, alpha: 1).CGColor)
array.append(UIColor(red: 0.2, green: 0, blue: 0, alpha: 1).CGColor)
progressColor.m_colors = array
return progressColor
}
}
ColorProgressView.swift
import UIKit
class ColorProgressView: UIView {
// MARK: -外部变量
var m_progress : Float? {
willSet {
if newValue <= 0 {
m_baseView?.frame = CGRect(x: 0, y: 0, width: 0, height: m_height!)
} else if newValue <= 1 {
m_baseView?.frame = CGRect(x: 0, y: 0, width: CGFloat(newValue!) * m_width!, height: m_height!)
} else {
m_baseView?.frame = CGRect(x: 0, y: 0, width: m_width!, height: m_height!)
}
}
}
var m_color : ProgressColor?
// MARK: -内部变量
private
var m_width : CGFloat?
private
var m_height : CGFloat?
private
var m_baseView : UIView?
private
var m_gradientLayer : CAGradientLayer?
private
let m_timer = GCDTimer(inQueue: GCDQueue.mainQueue())
// 开始进度
func startProgress() {
self.m_gradientLayer?.colors = self.m_color?.m_colors
self.m_gradientLayer?.startPoint = (self.m_color?.m_startPoint)!
self.m_gradientLayer?.endPoint = (self.m_color?.m_endPoint)!
self.m_timer.event({ () -> Void in
self.doProgress()
}, timeIntervalWithSecs: Float((self.m_color?.m_duration)!))
self.m_timer.start()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.m_width = frame.size.width
self.m_height = frame.size.height
// Base View
self.m_baseView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: self.m_height!))
self.m_baseView?.layer.masksToBounds = true
self.addSubview(self.m_baseView!)
// CAGradientLayer
self.m_gradientLayer = CAGradientLayer()
self.m_gradientLayer?.frame = self.bounds
self.m_baseView?.layer.addSublayer(self.m_gradientLayer!)
// ProgressColor
self.m_color = ProgressColor()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// 颜色移动
func doProgress() {
self.m_color?.m_colors = self.m_color?.loopMove()
self.m_gradientLayer?.colors = self.m_color?.m_colors
}
}
ViewController.swift
import UIKit
let ScreenWidth = UIScreen.mainScreen().bounds.size.width
class ViewController: UIViewController {
let m_timer = GCDTimer(inQueue: GCDQueue.mainQueue())
var m_counter : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blackColor()
// 红色进度条
let redProgressView = ColorProgressView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: 1))
redProgressView.m_color = ProgressColor.redGradientColor()
redProgressView.center = self.view.middlePoint
redProgressView.y -= 20
redProgressView.startProgress()
self.view.addSubview(redProgressView)
// 彩色进度条
let colorProgressView = ColorProgressView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: 5))
colorProgressView.center = self.view.middlePoint
colorProgressView.y += 20
colorProgressView.startProgress()
self.view.addSubview(colorProgressView)
// 关于闭包内,内存管理的问题,参见http://swifter.tips/retain-cycle/
self.m_timer.event({ () -> Void in
UIView.animateWithDuration(0.5, delay: 0,
usingSpringWithDamping: 2,
initialSpringVelocity: 0,
options: .CurveLinear,
animations: { [unowned self]() -> Void in
if self.m_counter == 100 {
self.m_counter = 0
} else {
self.m_counter += 10
}
redProgressView.m_progress = Float(self.m_counter) / 100.0
colorProgressView.m_progress = Float(self.m_counter) / 100.0
}, completion: nil)
}, timeIntervalWithSecs: 1.0, delaySecs: 1.0)
self.m_timer.start()
}
}