Refactor codes for circular progress UI.
This commit is contained in:
parent
1b0197ed2c
commit
20d818b2c2
@ -15,6 +15,10 @@ import UIKit
|
||||
return model as? CircularProgressBarModel
|
||||
}
|
||||
|
||||
var viewWidth: CGFloat {
|
||||
graphModel?.diameter ?? CGFloat(84)
|
||||
}
|
||||
|
||||
private var progressLayer = CAShapeLayer()
|
||||
private var tracklayer = CAShapeLayer()
|
||||
private var labelLayer = CATextLayer()
|
||||
@ -25,18 +29,16 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
var setTrackColor: UIColor = UIColor.white {
|
||||
var setTrackColor: UIColor = UIColor.lightGray {
|
||||
didSet {
|
||||
tracklayer.strokeColor = setTrackColor.cgColor
|
||||
}
|
||||
}
|
||||
/**
|
||||
A path that consists of straight and curved line segments that you can render in your custom views.
|
||||
Meaning our CAShapeLayer will now be drawn on the screen with the path we have specified here
|
||||
*/
|
||||
|
||||
// A path with which CAShapeLayer will be drawn on the screen
|
||||
private var viewCGPath: CGPath? {
|
||||
|
||||
let width = graphModel?.diameter ?? 84
|
||||
let width = viewWidth
|
||||
let height = width
|
||||
|
||||
return UIBezierPath(arcCenter: CGPoint(x: width / 2.0, y: height / 2.0),
|
||||
@ -45,9 +47,51 @@ import UIKit
|
||||
endAngle: CGFloat(1.5 * Double.pi), clockwise: true).cgPath
|
||||
}
|
||||
|
||||
// MARK: setup
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
|
||||
heightConstraint?.isActive = true
|
||||
widthAnchor.constraint(equalTo: heightAnchor).isActive = true
|
||||
}
|
||||
|
||||
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CircularProgressBarModel else { return }
|
||||
|
||||
// set background color
|
||||
if let backgroundColor = model.backgroundColor {
|
||||
self.backgroundColor = backgroundColor.uiColor
|
||||
} else {
|
||||
self.backgroundColor = UIColor.clear
|
||||
}
|
||||
|
||||
configureProgressViewToBeCircular()
|
||||
|
||||
// set progress color
|
||||
if let color = model.color {
|
||||
setProgressColor = color.uiColor
|
||||
} else {
|
||||
setProgressColor = UIColor.red
|
||||
}
|
||||
|
||||
// set track color
|
||||
if let trackColor = model.trackColor {
|
||||
setTrackColor = trackColor.uiColor
|
||||
} else {
|
||||
setProgressColor = UIColor.lightGray
|
||||
}
|
||||
|
||||
// show circular progress view with animation.
|
||||
showProgressWithAnimation(duration: 0.5, value: Float(graphModel?.percent ?? 0) / 100)
|
||||
|
||||
// show progress percentage label.
|
||||
showProgressPercentage()
|
||||
}
|
||||
|
||||
private func configureProgressViewToBeCircular() {
|
||||
let lineWidth = graphModel?.lineWidth ?? 2.0
|
||||
self.backgroundColor = UIColor.clear
|
||||
let lineWidth = graphModel?.lineWidth ?? 5.0
|
||||
|
||||
self.drawShape(using: tracklayer, lineWidth: lineWidth)
|
||||
self.drawShape(using: progressLayer, lineWidth: lineWidth)
|
||||
@ -60,7 +104,8 @@ import UIKit
|
||||
self.layer.addSublayer(shape)
|
||||
}
|
||||
|
||||
func setProgressWithAnimation(duration: TimeInterval, value: Float) {
|
||||
// value range is [0,1]
|
||||
private func showProgressWithAnimation(duration: TimeInterval, value: Float) {
|
||||
let animation = CABasicAnimation(keyPath: "strokeEnd")
|
||||
animation.duration = duration
|
||||
|
||||
@ -71,47 +116,26 @@ import UIKit
|
||||
progressLayer.add(animation, forKey: "animateCircle")
|
||||
}
|
||||
|
||||
func drawLabel() {
|
||||
private func showProgressPercentage() {
|
||||
|
||||
let percent = graphModel?.percent ?? 0
|
||||
let percentLen = percent > 9 ? 2 : 1
|
||||
|
||||
// configure attributed string for progress percentage.
|
||||
let attributedString = NSMutableAttributedString(string: String(percent) + "%")
|
||||
// percent value
|
||||
attributedString.setAttributes([NSAttributedString.Key.font: MFStyler.fontBoldTitleLarge()], range: NSMakeRange(0, percentLen))
|
||||
// % symbol
|
||||
attributedString.setAttributes([NSAttributedString.Key.font: MFStyler.fontBoldBodyLarge()], range: NSMakeRange(percentLen, 1))
|
||||
|
||||
// Text layer
|
||||
let width = graphModel?.diameter ?? 84
|
||||
// show progress percentage in a text layer
|
||||
let width = viewWidth
|
||||
let height = width
|
||||
labelLayer.string = attributedString
|
||||
labelLayer.frame = CGRectMake((width - CGFloat(percentLen * 20))/2, (height - 30)/2, 60, 30)
|
||||
self.layer.addSublayer(labelLayer)
|
||||
}
|
||||
|
||||
// MARK: setup
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
heightConstraint = heightAnchor.constraint(equalToConstant: 0)
|
||||
heightConstraint?.isActive = true
|
||||
widthAnchor.constraint(equalTo: heightAnchor).isActive = true
|
||||
}
|
||||
|
||||
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CircularProgressBarModel else { return }
|
||||
|
||||
configureProgressViewToBeCircular()
|
||||
|
||||
if let color = model.color {
|
||||
setProgressColor = color.uiColor
|
||||
}
|
||||
|
||||
if let backgroundColor = model.backgroundColor {
|
||||
setTrackColor = backgroundColor.uiColor
|
||||
}
|
||||
|
||||
setProgressWithAnimation(duration: 0.5, value: Float(graphModel?.percent ?? 0) / 100)
|
||||
drawLabel()
|
||||
}
|
||||
|
||||
//MARK: MVMCoreUIViewConstrainingProtocol
|
||||
public func needsToBeConstrained() -> Bool {
|
||||
|
||||
@ -22,9 +22,10 @@ public class CircularProgressBarModel: MoleculeModelProtocol {
|
||||
public var diameter: CGFloat = 84
|
||||
public var lineWidth: CGFloat = 5
|
||||
public var color: Color?
|
||||
public var backgroundColor: Color?
|
||||
public var trackColor: Color?
|
||||
public var percent: Int?
|
||||
|
||||
public var backgroundColor: Color? = Color(uiColor: UIColor.clear)
|
||||
|
||||
public init() {
|
||||
updateSize()
|
||||
}
|
||||
@ -35,8 +36,9 @@ public class CircularProgressBarModel: MoleculeModelProtocol {
|
||||
case diameter
|
||||
case lineWidth
|
||||
case color
|
||||
case backgroundColor
|
||||
case trackColor
|
||||
case percent
|
||||
case backgroundColor
|
||||
case moleculeName
|
||||
}
|
||||
|
||||
@ -58,8 +60,10 @@ public class CircularProgressBarModel: MoleculeModelProtocol {
|
||||
}
|
||||
|
||||
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
trackColor = try typeContainer.decodeIfPresent(Color.self, forKey: .trackColor)
|
||||
percent = try typeContainer.decodeIfPresent(Int.self, forKey: .percent)
|
||||
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -69,9 +73,10 @@ public class CircularProgressBarModel: MoleculeModelProtocol {
|
||||
try container.encode(size, forKey: .size)
|
||||
try container.encode(diameter, forKey: .diameter)
|
||||
try container.encode(lineWidth, forKey: .lineWidth)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(trackColor, forKey: .trackColor)
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
try container.encodeIfPresent(percent, forKey: .percent)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
}
|
||||
|
||||
func getCGColorsFromArray(_ colorArray: [String]) -> [Color] {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user