如何在 Swift 中使用 CoreGraphics 显示静态非动画进度条?
How to show a static NON-animated progress bar using CoreGraphics in Swift?
我想制作一个完全没有动画的静态进度条。我只想像 一样填充橙色部分,这张图片显示了(3 个中的 1 个)的进度,我想知道如何完成这个视图(3 个中的 2 个)并最终完成进度条,如(3 个中的 3 个)。
谢谢您,我们将不胜感激。
这是一个可以设计的作品 class
import Foundation
import UIKit
@IBDesignable
class StaticLoad: UIView {
enum Progress {
case Empty
case Filled(num: Int)
case Full
}
@IBInspectable public var progressColor: UIColor? {
didSet {
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
@IBInspectable public var nonProgressColor: UIColor = .gray {
didSet {
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
@IBInspectable public var numberOfSteps: Int = 3 {
didSet {
redrawSteps(step: numberOfSteps)
updateColor(progressColor: progressColor ?? self.tintColor, nonProgressColor: nonProgressColor)
}
}
@IBInspectable public var filledProgess: Int = 1 {
didSet {
if filledProgess >= numberOfSteps {
filledProgess = numberOfSteps
progress = .Full
}
if filledProgess <= 0 {
filledProgess = 0
progress = .Empty
} else {
progress = .Filled(num: filledProgess)
}
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
private var tip: CGFloat = 5
private var progress: Progress = .Empty
private var progressLayers: [CAShapeLayer] = []
private func updateColor(progressColor: UIColor, nonProgressColor: UIColor) {
switch progress {
case .Empty:
progressLayers.forEach { [=10=].fillColor = nonProgressColor.cgColor }
case let .Filled(num):
progressLayers.dropFirst(num).forEach { [=10=].fillColor = nonProgressColor.cgColor }
progressLayers.dropLast(progressLayers.count - num).forEach { [=10=].fillColor = progressColor.cgColor }
case .Full :
progressLayers.forEach { [=10=].fillColor = progressColor.cgColor }
}
}
private func redrawSteps(step: Int) {
progressLayers.forEach { [=10=].removeFromSuperlayer() }
progressLayers.removeAll()
if step == 0 {
let layer = CAShapeLayer()
layer.frame = self.bounds
progressLayers.append(layer)
} else {
var topLeft = CGPoint(x: 0, y: 0)
let cgStep = CGFloat(step)
let avaibleWidth = self.bounds.width - (2 * (cgStep - 1))
let spacePerStep = avaibleWidth / cgStep
let height = bounds.height
let halfHeight = height / 2
for i in 0..<step {
let layer = CAShapeLayer()
let bezier = UIBezierPath()
bezier.move(to: topLeft)
bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep, y: topLeft.y))
if i + 1 != step {
bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep + tip, y: topLeft.y + halfHeight))
}
bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep, y: topLeft.y + height))
bezier.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y + height))
if i != 0 {
bezier.addLine(to: CGPoint(x: topLeft.x + tip, y: topLeft.y + halfHeight))
}
bezier.close()
layer.path = bezier.cgPath
progressLayers.append(layer)
self.layer.addSublayer(layer)
topLeft.x = topLeft.x + spacePerStep + 2
}
}
}
override func layoutSubviews() {
redrawSteps(step: numberOfSteps)
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
您所要做的就是从情节提要中获取一个 UIView 并进行自定义 class StaticLoad
。您可以通过代码或故事板更改 numberOfSteps
属性 来指定进度条中的条数,并通过 filledProgress
填充条
如果您想要更大的箭头,只需更改 tip
属性,或为 bezierPath 指定其他路径。
如果你不知道,@IBDesignable
(建议如果class是可设计的,因为要不断编译,建议放在另一个框架而不是同一个项目)允许故事板渲染视图,@IBInspectable
允许通过故事板设置变量。
这是一个未优化的工作示例。
我想制作一个完全没有动画的静态进度条。我只想像
谢谢您,我们将不胜感激。
这是一个可以设计的作品 class
import Foundation
import UIKit
@IBDesignable
class StaticLoad: UIView {
enum Progress {
case Empty
case Filled(num: Int)
case Full
}
@IBInspectable public var progressColor: UIColor? {
didSet {
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
@IBInspectable public var nonProgressColor: UIColor = .gray {
didSet {
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
@IBInspectable public var numberOfSteps: Int = 3 {
didSet {
redrawSteps(step: numberOfSteps)
updateColor(progressColor: progressColor ?? self.tintColor, nonProgressColor: nonProgressColor)
}
}
@IBInspectable public var filledProgess: Int = 1 {
didSet {
if filledProgess >= numberOfSteps {
filledProgess = numberOfSteps
progress = .Full
}
if filledProgess <= 0 {
filledProgess = 0
progress = .Empty
} else {
progress = .Filled(num: filledProgess)
}
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
private var tip: CGFloat = 5
private var progress: Progress = .Empty
private var progressLayers: [CAShapeLayer] = []
private func updateColor(progressColor: UIColor, nonProgressColor: UIColor) {
switch progress {
case .Empty:
progressLayers.forEach { [=10=].fillColor = nonProgressColor.cgColor }
case let .Filled(num):
progressLayers.dropFirst(num).forEach { [=10=].fillColor = nonProgressColor.cgColor }
progressLayers.dropLast(progressLayers.count - num).forEach { [=10=].fillColor = progressColor.cgColor }
case .Full :
progressLayers.forEach { [=10=].fillColor = progressColor.cgColor }
}
}
private func redrawSteps(step: Int) {
progressLayers.forEach { [=10=].removeFromSuperlayer() }
progressLayers.removeAll()
if step == 0 {
let layer = CAShapeLayer()
layer.frame = self.bounds
progressLayers.append(layer)
} else {
var topLeft = CGPoint(x: 0, y: 0)
let cgStep = CGFloat(step)
let avaibleWidth = self.bounds.width - (2 * (cgStep - 1))
let spacePerStep = avaibleWidth / cgStep
let height = bounds.height
let halfHeight = height / 2
for i in 0..<step {
let layer = CAShapeLayer()
let bezier = UIBezierPath()
bezier.move(to: topLeft)
bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep, y: topLeft.y))
if i + 1 != step {
bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep + tip, y: topLeft.y + halfHeight))
}
bezier.addLine(to: CGPoint(x: topLeft.x + spacePerStep, y: topLeft.y + height))
bezier.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y + height))
if i != 0 {
bezier.addLine(to: CGPoint(x: topLeft.x + tip, y: topLeft.y + halfHeight))
}
bezier.close()
layer.path = bezier.cgPath
progressLayers.append(layer)
self.layer.addSublayer(layer)
topLeft.x = topLeft.x + spacePerStep + 2
}
}
}
override func layoutSubviews() {
redrawSteps(step: numberOfSteps)
updateColor(progressColor: progressColor ?? tintColor, nonProgressColor: nonProgressColor)
}
}
您所要做的就是从情节提要中获取一个 UIView 并进行自定义 class StaticLoad
。您可以通过代码或故事板更改 numberOfSteps
属性 来指定进度条中的条数,并通过 filledProgress
如果您想要更大的箭头,只需更改 tip
属性,或为 bezierPath 指定其他路径。
如果你不知道,@IBDesignable
(建议如果class是可设计的,因为要不断编译,建议放在另一个框架而不是同一个项目)允许故事板渲染视图,@IBInspectable
允许通过故事板设置变量。
这是一个未优化的工作示例。