// // RCGradientProgressView.swift // RemoteControlUnit // // Created by lsp on 2021/7/21. // import UIKit open class RCGradientProgressView: UIView { //進度條完成部分的漸變顏色,設置單個為純色,設置多個為漸變色 public var progressColors: [UIColor] = [.blue] { didSet { if progressColors.count == 0 { gradientLayer.colors = nil } else if progressColors.count == 1 { let color = progressColors[0] gradientLayer.colors = [color, color].map { $0.cgColor } } else { gradientLayer.colors = progressColors.map { $0.cgColor } } } } //進度條完成部分的圓角半徑 public var progressCornerRadius: CGFloat = 0 { didSet { maskLayer.cornerRadius = progressCornerRadius } } //漸變Layer public let gradientLayer: CAGradientLayer = { let layer = CAGradientLayer() layer.anchorPoint = .zero layer.startPoint = .zero layer.endPoint = CGPoint(x: 1.0, y: 0.0) return layer }() //動畫持續時間 public var animationDuration: TimeInterval = 0.3 //動畫時間函數 public var timingFunction: CAMediaTimingFunction = CAMediaTimingFunction(name: .default) private var privateProgress: Float = 0 private let maskLayer: CALayer = { let layer = CALayer() layer.backgroundColor = UIColor.white.cgColor return layer }() //當前進度 public var progress: Float { get { return privateProgress } set { setProgress(newValue, animated: false) } } public override init(frame: CGRect) { super.init(frame: frame) setupUI() } required public init?(coder: NSCoder) { super.init(coder: coder) setupUI() } func setupUI() { let color = progressColors[0] gradientLayer.colors = [color, color].map { $0.cgColor } gradientLayer.mask = maskLayer layer.insertSublayer(gradientLayer, at: 0) } open override func layoutSubviews() { super.layoutSubviews() // 沒有內間距 gradientLayer.frame = bounds.inset(by: .zero) var bounds = gradientLayer.bounds bounds.size.width *= CGFloat(progress) maskLayer.frame = bounds } public func setProgress(_ progress: Float, animated: Bool) { let validProgress = min(1.0, max(0.0, progress)) if privateProgress == validProgress { return } privateProgress = validProgress //動畫時長 var duration = animated ? animationDuration : 0 if duration < 0 { duration = 0 } CATransaction.begin() CATransaction.setAnimationDuration(duration) CATransaction.setAnimationTimingFunction(timingFunction) //更新maskLayer的frame var bounds = self.gradientLayer.bounds bounds.size.width *= CGFloat(validProgress) self.maskLayer.frame = bounds CATransaction.commit() } }
使用:
lazy var progressView: RCGradientProgressView = {
$0.layer.cornerRadius = 5
$0.progressCornerRadius = 5
$0.backgroundColor = .gray
$0.progressColors = [.orange, .blue]
// $0.animationDuration = 2.0
return $0
}(RCGradientProgressView(frame: CGRect(x: 20, y: 100, width: self.view.bounds.size.width - 40, height: 10)))
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
progressView.setProgress(0.6, animated: true)
}