Add support for circular progress bar.
This commit is contained in:
parent
fdab57200d
commit
7fec6f540e
@ -153,6 +153,8 @@
|
|||||||
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */; };
|
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */; };
|
||||||
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; };
|
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; };
|
||||||
4B002ACA2BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */; };
|
4B002ACA2BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */; };
|
||||||
|
4B3408A22C3873B0003BFABF /* CircularProgressBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3408A12C3873B0003BFABF /* CircularProgressBarModel.swift */; };
|
||||||
|
4B3408A42C3873E8003BFABF /* CircularProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3408A32C3873E8003BFABF /* CircularProgressBar.swift */; };
|
||||||
522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; };
|
522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; };
|
||||||
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; };
|
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; };
|
||||||
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; };
|
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; };
|
||||||
@ -770,6 +772,8 @@
|
|||||||
444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = "<group>"; };
|
444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = "<group>"; };
|
||||||
4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = "<group>"; };
|
4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = "<group>"; };
|
||||||
4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateDropdownEntryFieldModel+Extension.swift"; sourceTree = "<group>"; };
|
4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateDropdownEntryFieldModel+Extension.swift"; sourceTree = "<group>"; };
|
||||||
|
4B3408A12C3873B0003BFABF /* CircularProgressBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressBarModel.swift; sourceTree = "<group>"; };
|
||||||
|
4B3408A32C3873E8003BFABF /* CircularProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressBar.swift; sourceTree = "<group>"; };
|
||||||
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = "<group>"; };
|
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||||
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||||
52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = "<group>"; };
|
52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||||
@ -2311,6 +2315,8 @@
|
|||||||
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */,
|
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */,
|
||||||
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
|
D28A838223CCBD3F00DFE4FC /* WheelModel.swift */,
|
||||||
943784F3236B77BB006A1E82 /* Wheel.swift */,
|
943784F3236B77BB006A1E82 /* Wheel.swift */,
|
||||||
|
4B3408A12C3873B0003BFABF /* CircularProgressBarModel.swift */,
|
||||||
|
4B3408A32C3873E8003BFABF /* CircularProgressBar.swift */,
|
||||||
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
|
943784F4236B77BB006A1E82 /* WheelAnimationHandler.swift */,
|
||||||
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
|
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */,
|
||||||
0AE98BB423FF18D2004C5109 /* Arrow.swift */,
|
0AE98BB423FF18D2004C5109 /* Arrow.swift */,
|
||||||
@ -3005,6 +3011,7 @@
|
|||||||
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
||||||
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
|
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
|
||||||
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
|
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
|
||||||
|
4B3408A42C3873E8003BFABF /* CircularProgressBar.swift in Sources */,
|
||||||
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */,
|
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */,
|
||||||
EA17584E2BC9895A00A5C0D9 /* ButtonIcon.swift in Sources */,
|
EA17584E2BC9895A00A5C0D9 /* ButtonIcon.swift in Sources */,
|
||||||
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */,
|
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */,
|
||||||
@ -3025,6 +3032,7 @@
|
|||||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
|
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
|
||||||
AA37CBD52519072F0027344C /* Stars.swift in Sources */,
|
AA37CBD52519072F0027344C /* Stars.swift in Sources */,
|
||||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
|
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
|
||||||
|
4B3408A22C3873B0003BFABF /* CircularProgressBarModel.swift in Sources */,
|
||||||
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */,
|
8D8067D32444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift in Sources */,
|
||||||
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
|
8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */,
|
||||||
D2874024249BA6F300BE950A /* MVMCoreUISplitViewController+Extension.swift in Sources */,
|
D2874024249BA6F300BE950A /* MVMCoreUISplitViewController+Extension.swift in Sources */,
|
||||||
|
|||||||
75
MVMCoreUI/Atomic/Atoms/Views/CircularProgressBar.swift
Normal file
75
MVMCoreUI/Atomic/Atoms/Views/CircularProgressBar.swift
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// CircularProgressBar.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Xi Zhang on 7/5/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objcMembers open class CircularProgressBar: View, MVMCoreUIViewConstrainingProtocol {
|
||||||
|
|
||||||
|
var heightConstraint: NSLayoutConstraint?
|
||||||
|
weak var gradientLayer: CALayer?
|
||||||
|
var graphModel: CircularProgressBarModel? {
|
||||||
|
return model as? CircularProgressBarModel
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 }
|
||||||
|
createGraphCircle(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
class func getAngle(_ piValue: Double) -> Double {
|
||||||
|
return piValue / (2.0 * Double.pi) * 360.0
|
||||||
|
}
|
||||||
|
|
||||||
|
class func getPiValue(_ angle: Double) -> Double {
|
||||||
|
return angle / 360.0 * 2.0 * Double.pi
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: circle
|
||||||
|
open func createGraphCircle(_ graphObject: CircularProgressBarModel) {
|
||||||
|
if let sublayers = layer.sublayers {
|
||||||
|
for sublayer in sublayers {
|
||||||
|
sublayer.removeAllAnimations()
|
||||||
|
sublayer.removeFromSuperlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
heightConstraint?.constant = graphObject.diameter
|
||||||
|
|
||||||
|
let gradient = CAGradientLayer()
|
||||||
|
gradient.type = .conic
|
||||||
|
gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
|
||||||
|
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
|
||||||
|
gradient.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
|
||||||
|
gradientLayer = gradient
|
||||||
|
layer.addSublayer(gradient)
|
||||||
|
|
||||||
|
let center = CGPoint(x: gradient.bounds.midX, y: gradient.bounds.midY)
|
||||||
|
let radius = (graphObject.diameter - graphObject.lineWidth) / 2.0
|
||||||
|
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: (3 / 2 * .pi), endAngle: -(1 / 2 * .pi), clockwise: false)
|
||||||
|
let mask = CAShapeLayer()
|
||||||
|
mask.fillColor = UIColor.clear.cgColor
|
||||||
|
mask.strokeColor = UIColor.white.cgColor
|
||||||
|
mask.lineWidth = graphObject.lineWidth
|
||||||
|
mask.path = path.cgPath
|
||||||
|
gradient.mask = mask
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: MVMCoreUIViewConstrainingProtocol
|
||||||
|
public func needsToBeConstrained() -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
99
MVMCoreUI/Atomic/Atoms/Views/CircularProgressBarModel.swift
Normal file
99
MVMCoreUI/Atomic/Atoms/Views/CircularProgressBarModel.swift
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// CircularProgressBarModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Xi Zhang on 7/5/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
public class CircularProgressBarModel: MoleculeModelProtocol {
|
||||||
|
|
||||||
|
public static var identifier: String = "circularProgress"
|
||||||
|
public var id: String = UUID().uuidString
|
||||||
|
|
||||||
|
public var size: GraphSize = .small {
|
||||||
|
didSet {
|
||||||
|
updateSize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var diameter: CGFloat = 84
|
||||||
|
public var lineWidth: CGFloat = 5
|
||||||
|
public var color: Color?
|
||||||
|
public var backgroundColor: Color?
|
||||||
|
public var percent: Int?
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
updateSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case id
|
||||||
|
case size
|
||||||
|
case diameter
|
||||||
|
case lineWidth
|
||||||
|
case color
|
||||||
|
case backgroundColor
|
||||||
|
case percent
|
||||||
|
case moleculeName
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||||
|
|
||||||
|
if let size = try typeContainer.decodeIfPresent(GraphSize.self, forKey: .size) {
|
||||||
|
self.size = size
|
||||||
|
}
|
||||||
|
updateSize()
|
||||||
|
|
||||||
|
if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) {
|
||||||
|
self.diameter = diameter
|
||||||
|
}
|
||||||
|
|
||||||
|
if let lineWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .lineWidth) {
|
||||||
|
self.lineWidth = lineWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color)
|
||||||
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
|
percent = try typeContainer.decodeIfPresent(Int.self, forKey: .percent)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(id, forKey: .id)
|
||||||
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
|
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(color, forKey: .color)
|
||||||
|
try container.encodeIfPresent(percent, forKey: .percent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCGColorsFromArray(_ colorArray: [String]) -> [Color] {
|
||||||
|
return colorArray.map { (colorString) -> Color in
|
||||||
|
return Color(uiColor: UIColor.mfGet(forHex: colorString))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateSize() {
|
||||||
|
switch size {
|
||||||
|
case .small:
|
||||||
|
diameter = MFSizeObject(standardSize: 20)?.getValueBasedOnApplicationWidth() ?? 20
|
||||||
|
lineWidth = MFSizeObject(standardSize: 4)?.getValueBasedOnApplicationWidth() ?? 4
|
||||||
|
break
|
||||||
|
case .medium:
|
||||||
|
diameter = MFSizeObject(standardSize: 100)?.getValueBasedOnApplicationWidth() ?? 100
|
||||||
|
lineWidth = MFSizeObject(standardSize: 8)?.getValueBasedOnApplicationWidth() ?? 8
|
||||||
|
break
|
||||||
|
case .large:
|
||||||
|
diameter = MFSizeObject(standardSize: 180)?.getValueBasedOnApplicationWidth() ?? 180
|
||||||
|
lineWidth = MFSizeObject(standardSize: 12)?.getValueBasedOnApplicationWidth() ?? 12
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user